2011-01-09 11 views
5

Io sto usando un ciclo for simile a questo per troncare tutti i nomi dei file in una cartella di 16 caratteri:bash: Tronca nomi dei file, mantenendo uniche

for i in *; do 
    Shortname=${i:0:16}  # Let's assume I don't need the extension 
    mv "$i" "$Shortname" 
done 

Il problema è: Ogni volta che due nomi di file hanno la stessi primi 16 caratteri, quello successivo sovrascriverà quello precedente (su OS X mv si comporta in questo modo).

Come è possibile verificare se esiste già un file con il nome "Shortname" e, in tal caso, sostituire l'ultimo carattere di "Shortname" con un numero. Quindi controlla di nuovo se esiste un file con quel nome e, in tal caso, prova un numero più alto. E così via. Se arriva al numero 9 e finora sono stati presi tutti i nomi, dovrebbe sostituire gli ultimi DUE caratteri di "Shortname" con "10" e verificare se quel file esiste già.

Esempio: Diciamo che ho una directory con i seguenti file in essa contenuti:

MyTerriblyLongLongFirstFile.jpg 
MyTerriblyLongLongSecondFile.jpg 
MyTerriblyLongLongThirdFile.jpg 
... 
MyTerriblyLongLongFourteenthFile.jpg 
... 
MyTerriblyLongLongOneHundredSixtySeventhFile.jpg 
... 
MyTerriblyLongLongFiveMillionthFile.jpg 

nota che le prime 16 lettere sono le stesse per tutti i file. Dopo aver eseguito lo script, mi piacerebbe loro di essere rinominati a questo:

MyTerriblyLongL1.jpg 
MyTerriblyLongL2.jpg 
MyTerriblyLongL3.jpg 
... 
MyTerriblyLong14.jpg 
... 
MyTerriblyLon167.jpg 
... 
MyTerribl5000000.jpg 

Non importa se "MyTerriblyLongLongFourteenthFile.jpg" viene rinominato in "MyTerriblyLong14.jpg", che dipende l'ordinamento alfabetico. È semplicemente importante che ognuno di essi abbia un nome univoco.

Qual è il modo migliore per farlo?

risposta

4

Provalo prima sui file di test. Il solito metodo di test usando echo invece di mv non ti dirà molto poiché le potenziali collisioni di nomi non verrebbero create.

#!/bin/bash 
num=1 
length=16 
for file in M*.jpg 
do 
    newname=$file 
    until [[ ! -f $newname ]] 
    do 
     ((sublen = length - ${#num})) 
     printf -v newname '%.*s%d' "$sublen" "$file" "$num" 
     ((num++)) 
    done 
    mv "$file" "$newname" 
done 

Testing:

$ touch MyTerriblyLongLongFilenames{a..k}.jpg 
$ touch MyTerriblyLongL3 
$ ls M* 
MyTerriblyLongL3     MyTerriblyLongLongFilenamesf.jpg 
MyTerriblyLongLongFilenamesa.jpg MyTerriblyLongLongFilenamesg.jpg 
MyTerriblyLongLongFilenamesb.jpg MyTerriblyLongLongFilenamesh.jpg 
MyTerriblyLongLongFilenamesc.jpg MyTerriblyLongLongFilenamesi.jpg 
MyTerriblyLongLongFilenamesd.jpg MyTerriblyLongLongFilenamesj.jpg 
MyTerriblyLongLongFilenamese.jpg MyTerriblyLongLongFilenamesk.jpg 
$ ./nocollide 
$ ls M* 
MyTerriblyLong10 MyTerriblyLongL1 MyTerriblyLongL4 MyTerriblyLongL7 
MyTerriblyLong11 MyTerriblyLongL2 MyTerriblyLongL5 MyTerriblyLongL8 
MyTerriblyLong12 MyTerriblyLongL3 MyTerriblyLongL6 MyTerriblyLongL9 
+0

Sei l'uomo. Molte grazie! – Martin