Rinomina i file multipli utilizzando gli script Bash


27

Voglio rinominare più file nella stessa directory usando gli script Bash. I nomi dei file sono i seguenti:

file2602201409853.p
file0901201437404.p  
file0901201438761.p  
file1003201410069.p  
file2602201410180.p

Voglio rinominare nel seguente formato:

file2503201409853.p
file2503201437404.p  
file2503201438761.p  
file2503201410069.p  
file2503201410180.p

Stavo leggendo il 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 usando 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. Che cosa sto facendo di sbagliato?



2
Non è possibile avere un'espressione modello sul lato destro di un'espressione sostitutiva dell'espansione dei parametri. Cosa ti aspettavi di essere dove si *trova?
Kojiro,

@Kiwy Quella domanda riguarda la rimozione di una parte del nome del file. Ergo, altamente duplicato.
un CVn il

2
La prossima volta, descrivi le modifiche al nome del file che desideri apportare (ho dovuto esaminarlo per un po 'prima di vedere le differenze e le somiglianze). Gli esempi sono buoni, ma una descrizione così come gli esempi è ancora migliore.
un CVn il

Risposte:


42

Avevi ragione a considerare di rinominare prima. La sintassi è un po 'strana se non sei abituato alle regex ma è di gran lunga il percorso più veloce / più 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 cablaggio di prova ( -vnsignifica essere prolisso ma non fare nulla) usando 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

8
Si noti che questo è il nome Perl su Debian e derivati ​​(Ubuntu, Mint, ...). Su altre distribuzioni Linux, renameè uno strumento di ridenominazione di file completamente diverso (fornito da Debian rename.ul).
Gilles 'SO- smetti di essere malvagio' il

Se la tua mancanza distributiva di tale strumento, guarda la risposta di @Michael Campbell. Penso che ogni distributore sostituisca il default renamecome ha fatto Debian.
Astery,

25

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


for f in file*; do mv $f ${f/${f:4:4}/2503}; doneanche questo funziona.
Avinash Raj,

Bello. Se vuoi solo fare una parola normale per la sostituzione delle parole, funziona come sed. es.for f in *Huge*; do mv $f ${f/Huge/Monstrous}; done
Eric

1
@Eric - Ho pubblicato la tua risposta come alternativa perché penso che sia più chiara ed elegante. Se vuoi anche pubblicarlo come risposta, eliminerò il mio. Grazie!
Yehosef,


Mi dà un errore: "mv: target 'FILE_NAME' non è una directory"
Aubrey

10

questa è davvero la risposta di @ Eric dall'alto, ma è una risposta elegante, quindi la ripubblico come una risposta corretta per attirare più attenzione su di essa.

for f in *Huge*; do mv $f ${f/Huge/Monstrous}; done

1
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 ho l'abitudine di consegnare i comandi di massa mv - come scritto è solo un'eco. Dovrai risolverlo prima che funzioni.


1

Un modo nativo semplice per farlo senza loop, con l' attraversamento delle directory :

find -type f | xargs -I {} mv {} {}.txt

Rinominerà tutti i file presenti.

E di seguito un esempio funzionante con parallelizzazione :

find -name "file*.p" | parallel 'f="{}" ; mv -- {} ${f:0:4}2503${f:8}'

Era un primo approccio semplice per immaginare una soluzione migliore. Se vuoi un comando funzionante, fai:
dtrckd

find -type f -name "file*.p" | parallel 'ext="{}" ; mv -- {} ${ext:0:4}2503${ext:8}'
dtrckd,

0

Se ti capita di fare molto questo genere di cose, cerca "rename.pl". È uno script perl, ma ti permette semplicemente di dargli un codice perl (come /// espressione), e farà una rinominazione di massa basata su quell'espressione o codice.

C'è una versione di base qui: http://stackoverflow.org/wiki/Rename.pl ma ci sono altre versioni fluttuanti in rete. È stato in giro per secoli e secoli.

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.