Alfabetizzare le parole nei nomi dei file usando sort?


8

Durante la lettura di esercitazioni su rinominare i file in batch in bash e usando il sortcomando per ordinare i contenuti dei file, non sono stato in grado di capire come combinare i due.

Ho una directory i cui contenuti sono ordinati usando i tag all'interno del nome file, simile a come il programma TagSpaces gestisce le cose. Aggiungo qualsiasi tag mi venga in mente alla fine del nome file quando lo creo o lo scarico. Ecco un esempio:

Sunrise (2) #wallpaper #4k #googleimages.jpg

Ora voglio esaminare tutti questi file e rinominarli in modo che i tag siano ordinati alfabeticamente, senza influire su nulla prima o dopo i tag (ad esempio il titolo di una foto o l'estensione del file). Quindi quanto sopra diventerebbe:

Sunrise (2) #4k #googleimages #wallpaper.jpg

Come posso farlo? Non riesco nemmeno a capire come passare il nome di un file , e non il suo contenuto, a un comando come sort, il cui output potrei forse indirizzare a mv.


non una risposta alla tua domanda, ma dovresti pubblicare una risposta su TagSpaces in Aggiunta di tag a file (PDF) e processo dalla riga di comando o dallo script : a prima vista sembra molto pertinente a quella domanda.
cas

Risposte:


5
#!/bin/bash

for i in dir_for_files/*; do
    filename=${i%%#*}
    sorted_tags=$(grep -o "#[^ .]*" <<< "$i" | sort -n | tr '\n' ' ')
    ext=${i#*.}
    echo mv "$i" "${filename}${sorted_tags% }.$ext"
done

test:

##### Before sorting #####    
$ ls -1 dir_for_files
Note (3) #textfile #notes #important.txt
Sunrise (2) #wallpaper #4k #googleimages.jpg
Sunset (2) #wallpaper #2k #images.jpg

$ ./sort_tags.sh

##### After sorting #####
$ ls -1 dir_for_files
Note (3) #important #notes #textfile.txt
Sunrise (2) #4k #googleimages #wallpaper.jpg
Sunset (2) #2k #images #wallpaper.jpg

3

Se hai il perl-based rename( prenamesu alcuni sistemi) allora potresti fare una divisione + ordinare i tag usando perl. Ad esempio, dato

$ ls *.jpg
Sunrise (2) #wallpaper #4k #googleimages.jpg

quindi (con qualche brutta lotta per rimuovere e sostituire il .jpgsuffisso)

$ rename -v 'my @F = split / #/, substr($_,0,-4); $_ = (join " #", shift @F, sort @F) . ".jpg"' *.jpg
Sunrise (2) #wallpaper #4k #googleimages.jpg renamed as Sunrise (2) #4k #googleimages #wallpaper.jpg

verifica

$ ls *.jpg
Sunrise (2) #4k #googleimages #wallpaper.jpg

Probabilmente c'è molto margine di miglioramento, ma spero che ti dia qualche idea.


3

Con zsh:

autoload zmv # best in ~/.zshrc
zmv -n '([^#]#)(\#*)(.*)' '$1${(j: :)${(os: :)2}}$3'

(rimuovere il -n(funzionamento a secco) se felice).

  • [^#]#: 0 o più caratteri non # ( #è come *in regexps)
  • s: : diviso nello spazio
  • o: ordina (ordina)
  • j: :: unisciti con lo spazio.

Quindi, stiamo dividendo la parte tra il primo #(incluso) e l'ultimo .(escluso) nello spazio, ordinando l'elenco risultante a cui uniamo nuovamente con lo spazio.

ricorsivamente:

zmv -n '(**/)([^#]#)(\#*)(.*)' '$1$2${(j: :)${(os: :)3}}$4'

Per consentire spazi nei nomi dei tag, potremmo dividere #e tagliare gli spazi finali, ordinare e unire #con:

zmv -n '([^#]#\#)(*)(.*)' '$1${(j: #:)${(os:#:)2}%% #}$3'

Aggiungi un (#qD)qualificatore glob se vuoi anche elaborare file nascosti (altri Dfile) o se vuoi elaborare file in directory nascoste.


2

Bella domanda!

Ecco il mio semplice bashscript per questo:

for file in *.jpg; do 
    afile=( ${file#*)} ); 
    echo mv "$file" "${file%%#*}$(echo $(sort<(printf "%s\n" "${afile[@]%%.*}"))).jpg";
done

Spiegazione:

  • In afile=( ${file#*)} );: stiamo convertendo la stringa in un array. In questo stato la shell sta eseguendo la divisione di parole con spazi a meno che non si citi la stringa.

    In ${file#*)}( cut-up-to-first-prefix ): stiamo togliendo tutto dall'inizio alla stringa) utilizzo, shell parameter expansionpoiché risulterà #wallpaper #4k #googleimages.jpgconsiderato ilfile="Sunrise (2) #wallpaper #4k #googleimages.jpg"

  • In ${file%%#*} ( cut-up-to-last-suffix ); inizio di spelatura dalla fine alla supplica della corda fino all'ultima #vista. questo risulteràSunrise (2)

  • In ${afile[@]%%.*}( cut-up-to-last-suffix ): come sopra, togliendo l'inizio dalla fine all'accattonaggio della stringa (qui in ogni array indicizzato) fino all'ultima .vista. questo risulterà #wallpaper #4k #googleimages, potremmo anche usare ${afile[@]%.*}meglio!

  • In printf "%s\n" "${afile[@]%%.*}" : stiamo stampando gli elementi dell'array con newline ( [@]usati per l'array indicizzato), (perché con newline? Perché li ordineremo e dovremmo dividere gli elementi in newline)

  • In $(sort<(printf "%s\n" "${afile[@]%%.*}")): stiamo ordinando gli elementi (o tag).

  • In $(echo $(sort<(printf "%s\n" "${afile[@]%%.*}"))) : come sopra ma abbiamo usato un echocomando extra per raccogliere gli elementi ordinati in quello lineare.

    possibile lo stesso anche con l'utilizzo del doppio xargslike ... |xargs -n1| sort | xargs.
    Vedi l'esempio seguente per comprendere meglio questo passaggio:

    echo -e "C\n4\nB" |sort
    4
    B
    C
    echo $(echo -e "C\n4\nB" |sort)
    4 B C

Finalmente alla fine, mv comando sta rinominando il $filenome modificato dovrebbe essere.

Ps: rimuovi echo mv ...davanti a mvper uscire dal ciclo a secco ed eseguire l'effettiva ridenominazione.


1

Sembra un po 'troppo complicato perché Bash sia sincero. Non è impossibile, ma secondo me, è molto meglio usare un linguaggio creato per una programmazione "reale" qui. Una soluzione di Bash sarà probabilmente impenetrabile. (Non tentando di insultare la soluzione solo Bash, penso che la rinominazione-magia sia piuttosto sorprendente, in realtà)

Detto questo, ecco una soluzione con Ruby. Puoi scriverlo su un file e quindi eseguire il file dalla shell, dato che hai installato Ruby.

#!/usr/bin/env ruby
Dir.glob('*.jpg').each do |filename|
    # `name` contains the name of the file, without the tags. `tags` is an array
    # of all tags of the file.
    name, *tags = filename.split(' #')
    # if there aren't any tags, just skip the file.
    if tags.empty?
        next
    end
    # remove the trailing '.jpg' and sort all the tags
    tags.last.gsub!(/\.jpg$/,'')
    tags.sort!
    tags = [name] + tags
    # finally, move the file to the correct location with sorted tags.
    File.rename filename, "#{tags.join(' #')}.jpg"
end

Per eseguire lo script, è sufficiente posizionarlo nella directory in cui si trovano le immagini. Questa soluzione dovrebbe essere abbastanza resistente ai nomi e ai tag di immagini stupide come C#non causerà problemi. Detto questo, assicurati di fare un backup prima di eseguire lo script. Le operazioni di movimento possono essere altrettanto distruttive come a rm.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.