Voglio rinominare più file nella stessa directory usando lo scripting Bash. I nomi dei file sono i seguenti:
file2602201409853.p file0901201437404.p file0901201438761.p file1003201410069.p file2602201410180.p
Desidero rinominare nel seguente formato:
file2503201409853.p file2503201437404.p file2503201438761.p file2503201410069.p file2503201410180.p
Stavo leggendo del comando rename e ho provato a farlo in questo modo, ma non fa nulla, penso di avere domande sulla sintassi. Poi ho letto che puoi creare un ciclo utilizzando il comando mv come segue:
for file in cmpsms*2014*.p; do mv "$file" "${file/cmpsms*2014*.p/cmpsms25032014*.p}" done
Ma non riesco a rinominare i file. Cosa sto facendo di sbagliato?
Commenti
Risposta
Hai fatto bene a considerare prima la ridenominazione. La sintassi è un po strana se “non sei abituato alle espressioni regolari, ma è di gran lunga il percorso più veloce / breve una volta che sai cosa stai” facendo:
rename "s/\d{4}/2503/" file*
Questo corrisponde semplicemente ai primi 4 numeri e li scambia con quelli che hai specificato.
E un test harness (-vn
significa essere verboso ma non “t fare qualsiasi cosa) utilizzando i nomi dei file:
$ rename "s/\d{4}/2503/" file* -vn file0901201437404.p renamed as file2503201437404.p file0901201438761.p renamed as file2503201438761.p file1003201410069.p renamed as file2503201410069.p file2602201409853.p renamed as file2503201409853.p file2602201410180.p renamed as file2503201410180.p
Commenti
- Nota che questa è la rinomina Perl su Debian e derivati (Ubuntu, Mint, …). Su altre distribuzioni Linux,
rename
è uno strumento di ridenominazione di file completamente diverso (che Debian fornisce comerename.ul
). - Se la tua mancanza distributiva di tale strumento, guarda la risposta di @Michael Campbell. Penso che ogni distribuzione sostituisca il valore predefinito
rename
come ha fatto Debian.
Risposta
Questo dovrebbe fare il trucco:
for f in file*; do mv $f ${f/${f:4:8}/25032014}; done
Sostituisce la stringa tra il 4 ° e il 12 ° carattere con “25032014”.
Commenti
- anche questo
for f in file*; do mv $f ${f/${f:4:4}/2503}; done
funziona. - Questo ' è carino. Se vuoi solo sostituire una parola per parola normale, funziona come sed. per esempio.
for f in *Huge*; do mv $f ${f/Huge/Monstrous}; done
- @Eric – Ho pubblicato la tua risposta come alternativa perché penso che ' sia più chiara ed elegante . Se vuoi pubblicarlo anche come risposta, ' elimino il mio. Grazie!
- Perché virgolette doppie mancanti?
- Mi dà un errore: " mv: target ' FILE_NAME ' non è una directory "
Risposta
questa è davvero la risposta di @Eric dallalto, ma è una risposta elegante quindi Lo ripubblico come una risposta adeguata per attirare più attenzione su di esso.
for f in *Huge*; do mv "$f" "${f/Huge/Monstrous}"; done
Answer
ptrn="file[0-9][0-9][0-9][0-9]2014[0-9][0-9][0-9][0-9][0-9].p" path=/dir ( set -- "${path}/"${ptrn} ; for f ; do { echo "mv ${path}/${f} \ ${path}/file25032014${f#2014}" } ; done )
Questo dovrebbe fare il trucco. Nota – Non sono abituato a consegnare comandi mv di massa – come scritto è” solo un eco. Tu ” dovrò risolverlo prima che “funzioni.
Risposta
Un modo semplice e nativo per farlo senza loop, con directory traversal :
find -type f | xargs -I {} mv {} {}.txt
Rinominerà ogni file in posizione.
E sotto un lavoro esempio di ingaggio con parallelizzazione :
find -name "file*.p" | parallel "f="{}" ; mv -- {} ${f:0:4}2503${f:8}"
Commenti
- È stato un primo approccio facile per immaginare una soluzione migliore. Se vuoi un comando funzionante:
-
find -type f -name "file*.p" | parallel 'ext="{}" ; mv -- {} ${ext:0:4}2503${ext:8}'
Rispondi
Se trovi che fai spesso questo genere di cose, cerca “rename.pl”. È “uno script Perl, ma ti permette semplicemente di alimentarlo con codice Perl (come /// espressione), e farà una ridenominazione di massa basata su quellespressione o codice.
Cè una versione base qui: http://stackoverflow.org/wiki/Rename.pl ma ci sono altre versioni che fluttuano nella rete. È in circolazione da secoli e secoli.
*
?