renombrar (1) un conjunto de archivos más allá del directorio actual

3

El renamecomando en Ubuntu 12.04 (la página del manual dice que es parte de perl v5.14.2 2012-03-23) funciona bien en un solo directorio, pero también quiero usarlo en subdirectorios (o, más generalmente, en una lista de archivos que está la salida de otro comando, a través de comillas inversas). Por ejemplo, esperaría

rename "s/ /-/g"  `find .`

para cambiar todos los espacios a guiones en todos los nombres de archivo debajo del directorio actual. Pero este comando no hace nada.

( Editar : cambiado rename -na rename. Esa opción es buena para experimentar de forma segura, pero solo es una distracción aquí).

Los backquotes no tienen la culpa, porque reemplazarlos find .con, por ejemplo, echo */*funciona.

Primero haciendo find . > foo, y luego reemplazando find .con cat foo, no hace nada.

Incluso colapsar la lista de archivos en una línea, al reemplazar find .con find . | tr -d '\n', no hace nada.

¿Qué elemento tiene la culpa?

Camille Goudeseune
fuente

Respuestas:

2

Esto no funcionará:

rename 's/ /-/g'  `find .`

Después de ejecutar el comando find, el shell divide las palabras en los resultados. En consecuencia, ningún nombre de archivo con espacios sobrevive al tacto: se divide en pedazos.

Puede evitar esto usando:

rename 's/ /-/g'  */*

En esta forma del comando, el shell no divide las palabras y renametendrá éxito. Este formulario funciona incluso para nombres de archivos con espacios, tabulaciones o cualquier otro carácter difícil.

Alternativamente, use find -exec:

find . -name '* *' -exec rename 's/ /-/g' {} +

Este formulario funcionará con nombres de archivos que tengan espacios, tabulaciones o cualquier otro carácter difícil.

Demostración

Para ver qué sale mal, creemos un archivo con espacios

$ touch "a b c"
$ find .
.
./a b c

Para aclarar lo que sucede, creemos una función para poner cada argumento que ve dentro de comillas dobles y mostrarlo:

$ display() { printf '"%s"\n' "$@"; }

Ahora, podemos usar displaypara ver qué sucede cuando ejecutamos find .:

$ display `find .`
"."
"./a"
"b"
"c"

Esto muestra la división de palabras en acción. El nombre del archivo a b cse dividió en tres palabras separadas.

John1024
fuente
"en tacto": veo lo que hiciste allí :-)
Camille Goudeseune
El espacio en blanco en los nombres de archivo es solo un ejemplo: podría ser uno mejor s/png/jpg/. Entonces, esta respuesta general se reduce a la solución alternativa de reemplazar las comillas inversas con find ... -exec rename ..., o find ... | xargs rename .... Entonces todavía me pregunto por qué fallan las comillas.
Camille Goudeseune
@CamilleGoudeseune "Así que todavía me pregunto por qué fallan las comillas inversas". No tiene nada que ver con qué comando sustituto se utiliza. Esto se debe a que los nombres de archivo con espacios en blanco en la línea de comando están sujetos a la división de palabras. De lo contrario, funciona.
John1024
Correcto. El espacio en blanco en los nombres de archivo es el único problema, después de todo. Hice un mejor caso de prueba desde cero y, sí, las comillas inversas funcionan. Lo siento por hacerte perder el tiempo.
Camille Goudeseune