2011-01-09 17 views
5

estoy usando un bucle for similar a éste para truncar los nombres de archivo en una carpeta de 16 caracteres:bash: truncar nombres de archivo, manteniéndolos única

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

El problema es: Siempre que dos nombres de archivo tienen la los primeros 16 primeros caracteres, el último sobrescribirá el anterior (en OS X mv se comporta de esa manera).

¿Cómo puedo comprobar si un archivo con el nombre "Nombre corto" ya existe, y si es así, reemplace el último carácter de "Nombre corto" con un número. Luego, verifique nuevamente si existe un archivo con ese nombre, y de ser así, intente con un número más alto. Y así. Si llega al número 9 y hasta ahora se han tomado todos los nombres, debería reemplazar los últimos DOS caracteres del "Nombre corto" con "10" y comprobar si ese archivo ya existe.

Ejemplo: Supongamos que tengo un directorio con los siguientes archivos en ella:

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

Tenga en cuenta que las primeras 16 letras son las mismas para todos los archivos. Después de ejecutar el guión, me gustaría que se cambiará a esto:

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

No importa si "MyTerriblyLongLongFourteenthFile.jpg" se cambia a "MyTerriblyLong14.jpg", que depende de la clasificación alfabética. Es importante que cada uno obtenga un nombre único.

¿Cuál es la mejor manera de hacerlo?

Respuesta

4

Primero pruebe esto en los archivos de prueba. El método habitual de prueba utilizando echo en lugar de mv no le dirá mucho, ya que no se crearían posibles colisiones de nombres.

#!/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 

Pruebas:

$ 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

usted es el hombre. ¡Muchas gracias! – Martin

Cuestiones relacionadas