Voglio rinominare tutti i file e le directory che contengono Word "speciale" a "normale". Dovrebbe mantenere la distinzione tra maiuscole e minuscole, quindi "Speciale" non diventerà "regolare".
Come posso farlo in modo ricorsivo in bash?
Prova a farlo (richiede bash --version
> = 4):
shopt -s globstar
rename -n 's/special/regular/' **
Rimuovi l'opzione -n
quando i tuoi test sono OK
Ci sono altri strumenti con lo stesso nome che potrebbero o meno essere in grado di farlo, quindi fai attenzione.
Se si esegue il seguente comando (GNU
)
$ file "$(readlink -f "$(type -p rename)")"
e hai un risultato come
.../rename: Perl script, ASCII text executable
e non contenente:
ELF
allora questo sembra essere lo strumento giusto =)
In caso contrario, per renderlo predefinito (di solito già il caso) su Debian
e derivativo come Ubuntu
:
$ Sudo update-alternatives --set rename /path/to/rename
(sostituisci /path/to/rename
al percorso del tuo comando Perl's rename
.
Se non hai questo comando, cerca nel tuo gestore pacchetti di installarlo o fallo manualmente
Ultimo ma non meno importante, questo strumento è stato originariamente scritto da Larry Wall, il padre di Perl.
Una soluzione che utilizza find
:
Per rinominare solo file :
find /your/target/path/ -type f -exec rename 's/special/regular/' '{}' \;
Per rinominare solo le directory :
find /your/target/path/ -type d -execdir rename 's/special/regular/' '{}' \+
Per rinominare entrambi i file e le directory :
find /your/target/path/ -execdir rename 's/special/regular/' '{}' \+
Se non ti dispiace installare un altro strumento, puoi usare rnm :
rnm -rs '/special/regular/g' -dp -1 *
Passerà attraverso tutte le directory/sottodirectory (a causa di -dp -1
) e sostituirà special con regular nei loro nomi.
@ risposta di speakr era l'indizio per me.
Se si utilizza -execdir per trasformare sia i file che le directory, sarà necessario rimuovere -type f
dall'esempio mostrato. Per spiegarlo, usa:
find /your/target/path/ -execdir rename 's/special/regular/' '{}' \+
Inoltre, considera l'aggiunta di g
(global) flag alla regex se si desidera sostituire all occorrenze di special
con regular
in un determinato nomefile e non solo la prima occorrenza. Per esempio:
find /your/target/path/ -execdir rename 's/special/regular/g' '{}' \+
trasformerà special-special.jpg
in regular-regular.jpg
. Senza la bandiera globale, finirai con regular-special.jpg
.
A proposito: GNU Rinomina non è installato di default su Mac OSX. Se si sta utilizzando Homebrew package manager , brew install rename
risolverà questo problema.
Per coloro che desiderano semplicemente rinominare le directory, è possibile utilizzare questo comando:
find /your/target/path/ -type d -execdir rename 's/special/regular/' '{}' \;
Il tipo di nota è ora d
per la directory e utilizza -execdir
.
Non sono stato in grado di capire come rinominare sia i file che le directory in un singolo passaggio.
Qualcuno ha commentato in precedenza che, una volta rinominata la cartella radice, non poteva più attraversare la struttura dei file. È disponibile uno switch -d
che esegue un deep traversal dal basso verso l'alto, quindi la root verrà rinominata all'ultimo credo:
find -d /your/target/path/ -type d -execdir rename 's/special/regular/' '{}' \;
Dalla pagina di manuale (man find
):
-d Cause find to perform a depth-first traversal, i.e., directories are visited in post-order and all entries in a directory will be
acted on before the directory itself. By default, find visits directories in pre-order, i.e., before their contents. Note, the
default is not a breadth-first traversal.
Ecco un altro approccio che è più portabile e fa non si basa sul comando rename
(poiché potrebbe richiedere parametri diversi a seconda delle distro).
Rinomina i file e le directory in modo ricorsivo:
find . -depth -name "*special*" | \
while IFS= read -r ent; do mv $ent ${ent%special*}regular${ent##*special}; done
Cosa fa
-depth
per riordinare i risultati eseguendo un depth-first traversal (cioè tutte le voci in una directory vengono visualizzate prima della directory stessa).In questo modo i file vengono prima modificati e poi ogni directory principale.
Esempio
Dando il seguente albero:
├── aa-special-aa
│ └── bb-special
│ ├── special-cc
│ ├── special-dd
│ └── Special-ee
└── special-00
Genera quei comandi mv
in quel particolare ordine:
mv ./aa-special-aa/bb-special/special-cc ./aa-special-aa/bb-special/regular-cc
mv ./aa-special-aa/bb-special/special-dd ./aa-special-aa/bb-special/regular-dd
mv ./aa-special-aa/bb-special ./aa-special-aa/bb-regular
mv ./aa-special-aa ./aa-regular-aa
mv ./special-00 ./regular-00
Per ottenere il seguente albero:
├── aa-regular-aa
│ └── bb-regular
│ ├── regular-cc
│ ├── regular-dd
│ └── Special-ee
└── regular-00