risposta-alla-domanda-sullo-sviluppo-web-bd.com

Rinominare i file e le directory in modo ricorsivo sotto ubuntu/bash

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? 

53
Tom

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

warning 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.

68
Gilles Quenot

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/' '{}' \+
88
speakr

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.

5
Jahid

@ 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.

2
U007D

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.
0
LokMac

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

  • usa find con il parametro -depth per riordinare i risultati eseguendo un depth-first traversal (cioè tutte le voci in una directory vengono visualizzate prima della directory stessa).
  • esegui sostituzioni di pattern per modificare solo l'ultima occorrenza di regular nel percorso.

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
0
jyvet