it-swarm-es.com

El código funciona en la terminal pero no en el script para renombrar (manipular nombres de archivos con espacios)

Quiero aprender más, así que he intentado escribir más que solo usar el terminal. Sé rename y puedo cambiar el nombre de los archivos de imagen con rename 's/ /_/g' *.jpg pero cuando lo escribo en un script de Shell para apuntar a un directorio:

DIRECTORY="/foo/bar"

for imgfile in $(find $DIRECTORY -type f -name \*.jpg); do
    echo 'replacing whitespace in' $(basename $imgfile)
    rename -f 's/ /_/g' *.jpg 
done

no funciona y el terminal tomará un archivo (ejemplo: 1234 abcd.jpg) y echo abcd.jpg. Entonces, ¿dónde me estoy equivocando?

Los espacios en los nombres de archivo son malvados.

Veo tres problemas con el guión.

1) al hacer el bucle for..., tendrá dos valores diferentes cuando encuentre un archivo con espacio. es decir, si tiene los archivos "file1 1.jpg" y "file2 2.jpg" y tiene:

for i in $(find . -type f -name \*.jpg); do 
   echo $i
done

Tendras

./file1 
1.jpg
./file2
2.jpg

porque el Shell rompe el argumento en los espacios. La salida del comando $(find ...) será

./file1 1.jpg 
./file2 2.jpg 

Cuáles son cuatro palabras para el comando for que se asignará en $i --- de forma predeterminada, el Shell trata los espacios y las nuevas líneas de la misma manera cuando se expande.

Puede eludir esto cambiando el carácter IFS .

Su primera línea podría verse así:

IFS=$'\n' find $DIRECTORY -type f -name \*.jpg | while read -r imgfile; do

2) está alimentando el bucle for con un solo nombre de archivo, por lo que debe decir:

rename -f 's/ /_/g' "$imgfile"

de lo contrario *.jpg se expande en el directorio actual, y no en $DIRECTORY (y tenga en cuenta las comillas --- dado que $imgfile va a tener espacios en él).

3) incluso entonces, si $DIRECTORY tiene algún componente de ruta con espacios, el cambio de nombre fallará (habrá directorios intermedios que no existen).

4) sugerencia (manteniéndolo simple):

DIRECTORY="/foo/bar"
cd $DIRECTORY
rename -f 's/ /_/g' *.jpg

no hace lo que quieres?

agregado : mi script (creado hace mucho tiempo, cuando no había rename en Unix), es esto --- eliminará espacios y pestaña en todos los archivos en el directorio actual que los tienen en el nombre:

# 
ls -1  | grep -E " |\t" | while read i; do
    a=`echo $i | tr " \t" "__"`
    mv -v "$i" $a
done

agregado ++ : este enlace Descubrí que investigar esta respuesta es excelente.

4
Rmano