Sottrai 1 da tutti i nomi di file (rinominali) in una directory.


17

Ho una directory che contiene file di immagini con nomi simili

image1.jpg 
image2.jpg 
image3.jpg
...

Sfortunatamente, i nomi delle immagini devono essere basati su zero, quindi image1.jpgdovrebbe essere image0.jpg, image2.jpgdovrebbe essere image1.jpge così via.

Posso scrivere uno script per generare comandi mv come questi, inserirli in uno script shell e quindi eseguirli -

mv image1.jpg image0.jpg
mv image2.jpg image1.jpg
mv image3.jpg image2.jpg
...

Ma suppongo che ci sia un modo più semplice per farlo in Unix. Quindi, cos'è?


6
Questo è in realtà il modo più semplice per farlo, purché non vi siano lacune. ( for i in $(seq 0 100); do mv image$[i+1].jpg image$i.jpg; done)
Ricky Beam,

5
L'ordine delle immagini è importante? In caso contrario, basta rinominare l'ultima immagine da imageN.jpga image0.jpge il gioco è fatto.
jnovacho,

@jnovacho, abbastanza intelligente! Ma sì, l'ordine delle immagini è importante.
Wes,

Risposte:


20

Il buon vecchio nome perl:

rename 's/(\d+)(\.jpg)/($1-1).$2/e' *

[Nota]

I numeri delle immagini devono essere maggiori di 0.

Nel caso in cui le immagini siano maggiori di 9 e non abbiano 0 iniziali, utilizzare $(ls -v1 *)per evitare il blocco. Proposto da @arielf e notato da @Graeme.

In caso di dubbio utilizzare anche -vper verbose e -nper nessuna azione.


Cosa indica la "e"?
Wes,

3
'e' significa valutare, verrà valutata la sezione di sostituzione. vedi ancheperlreref

6
I file devono essere passati in ordine crescente per evitare blocchi. Funzionerà bene solo se ci sono meno di 10 file (o se i numeri hanno zeri iniziali).
Graeme,

Ho notato questo già, inoltre non ci deve essere un 0nelle fonti.

2
sostituiscilo *alla fine con `ls -v1 *`e sarai più sicuro dall'ostruzione. Passerà dal numero più basso al più alto.
arielf

6

È possibile reindirizzare i mvcomandi generati a bash. Quindi non devi copiarli in uno script ed eseguirlo. Vedere:

command_that_generates_mv_commands | bash

E verrà eseguito tutto ciò che viene convogliato bash.


Non è più pulito. :)Risolve il problema però, quindi +1.
JMCF125,

5

Puoi iterare su ls output, questo funziona per il tuo esempio:

i=0 
for file in $(ls *.jpg | sort) ; do 
     mv $file $(echo $file | sed 's/[0-9]*.jpg$/'${i}'.jpg/')
     i=$((++i))
done

Devi essere sullo stesso percorso dei tuoi file


1
Meglio usare -io -ncon mv, eviterà la sovrascrittura in casi limite.
Graeme,

non sort -Vsarebbe meglio invece?
user80551

sortnon funzionerà, mostrerà image10.jpgprima image1.jpgche potrebbe essere un problema. È necessario sort -nk 1.8come nella risposta di @ Graeme.
terdon

@ user80551, sort -Vè una buona idea, lo aggiungerò alla mia risposta. Potrebbero esserci altri casi limite, tuttavia in genere un buon consiglio per aggiungere questo tipo di opzioni con domande come questa nel caso in cui qualcuno copi e finisca per fare un danno.
Graeme,

4

Quanto segue sembra funzionare per tutto ciò che si adatta al modello imageNUMBER.jpg. Ho messo echoprima del mvcomando per mostrare prima cosa avrebbe fatto il comando; per eseguire effettivamente la ridenominazione, basta rimuovere ilecho

for i in `ls image*.jpg|sort -V` ; do 
    x=`echo $i|sed -e "s/image\(.*\).jpg/\1/"`
    y=$(( $x - 1 ))
    echo mv -i $i image$y.jpg
done

Nella prima riga, i ls image*.jpg|sort -Vfile JPG verranno elencati con un numero crescente nel nome del file. La x=riga estrae il numero dal nome file. La y=riga quindi decrementa il numero di uno. Il nome file di input e il ynumero vengono quindi utilizzati nel mvcomando, in cui il -iflag ti avviserà prima di sovrascrivere un file.

Per il mio piccolo test, questo ha prodotto l'output:

mv -i image1.jpg image0.jpg
mv -i image2.jpg image1.jpg
mv -i image123.jpg image122.jpg

Personalmente, suggerirei di rinominare un nome file più diverso, poiché ora l'ordine in cui i file vengono elaborati può fare una grande differenza.


1
Meglio usare -io -ncon mv, eviterà la sovrascrittura in casi limite.
Graeme,

Ottimo suggerimento, modificherò la risposta
brm

In macOS, dovresti usare sort -n, l' -Vopzione non esiste.
Vincent Sit,

4

L'uso dello perlscript prename, che è simbolicamente collegato per rinominare le distribuzioni basate su Debian, necessita anche di GNU find/ sort. I file vengono messi in ordine crescente per impedire la sovrascrittura.

find . -regex '\./image[0-9]+\.jpg' -print0 | sort -zV |
  xargs -0 rename -n 's/(\d+)\.jpg$/@{[$1-1]}.jpg/'

Rimuovi -nuna volta che sei sicuro che fa quello che vuoi. Avverterà sui file già esistenti prima di farlo. Tuttavia, fintanto che mostra i file che vengono rinominati in ordine crescente, non ci saranno conflitti quando eseguiti per davvero.


Il file esiste già problemi con questo.
Wes,

4

Con zsh:

autoload zmv # (in ~/.zshrc)
zmv -Qf -n 'image(<->).jpg(n)' 'image$(($1-1)).jpg'

(rimuovere -nquando felice).

(n)consiste nell'ordinare numericamente l'elenco in modo da image9.jpgessere rinominato prima image10.jpg.

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.