Cómo cambiar el nombre de varios archivos en un directorio al mismo tiempo

12

Tengo un directorio /var/tmp/abcque dice que tiene 4 archivos:

12345-ram-3e3r5-io9490-89adu9.csv
45434-dam-qwe35-to9490-43adu9.csv
11234-cam-yy3r5-ro9490-85adu9.csv
14423-sam-hh3r5-uo9490-869du9.csv

Quiero cambiar el nombre de todos los archivos CSV (encontrar todos los archivos y cambiarles el nombre) de la manera más breve posible (probablemente de una sola línea) para esto:

XXXXX-ram-3e3r5-io9490-89adu9.csv
XXXXX-dam-qwe35-to9490-43adu9.csv
XXXXX-cam-yy3r5-ro9490-85adu9.csv
XXXXX-sam-hh3r5-uo9490-869du9.csv
Rocky86
fuente

Respuestas:

15

rename -n 's/(\w+)/XXXXX/' *.csv

eliminar el -ncuando feliz.

Shawarden
fuente
2
Para una versión adecuada de rename. Supongo que esto es de Larry Wall rename, del renamepaquete en Debian y derivados (y IIRC prenameen sistemas de persuasión RedHat). Una herramienta muy útil.
xenoid
2
perl-renameen arch linux
lesmana
1
@SHawarden, he intentado ejecutar el comando y leer la parte correspondiente de la página del manual para comprender el patrón de reemplazo, pero al agregar el verboseindicador, no muestra nada y no realiza los cambios de nombre de archivo, aunque la ruta actual tenga archivos con nombres similares a 12345_foo.csv. ¿Tengo que realizar alguna tarea adicional para que funcione (actualmente en Fedora 30)? Es un enfoque más limpio que el bucle. ¡Gracias por adelantado!
danieldeveloper001
3
@ danieldeveloper001 ¿Usaste renameo prename? Ver mi comentario arriba. man {the command}enumera los autores al final.
xenoid
2
Esto solo funciona en sistemas derivados de Debian. Los sistemas derivados de Fedora tienen un renamecomando completamente diferente ; ver unix.stackexchange.com/a/238862/135943
Wildcard
11

Tratar:

for f in *.csv; do mv -i -- "$f" "XXXXX-${f#*-}"; done

Cómo funciona:

  • for f in *.csv; do

    Esto inicia un ciclo sobre todos los *.csvarchivos.

  • mv -i -- "$f" "XXXXX-${f#*-}"

    Esto cambia el nombre de los archivos como desee, preguntando interactivamente antes de sobrescribir cualquier archivo.

  • done

    Esto marca el final del ciclo.

Ejemplo:

$ ls -1
11234-cam-yy3r5-ro9490-85adu9.csv
12345-ram-3e3r5-io9490-89adu9.csv
14423-sam-hh3r5-uo9490-869du9.csv
45434-dam-qwe35-to9490-43adu9.csv
$ for f in *.csv; do mv -i -- "$f" "XXXXX-${f#*-}"; done
$ ls -1
XXXXX-cam-yy3r5-ro9490-85adu9.csv
XXXXX-dam-qwe35-to9490-43adu9.csv
XXXXX-ram-3e3r5-io9490-89adu9.csv
XXXXX-sam-hh3r5-uo9490-869du9.csv
John1024
fuente
4

Me gustó el pequeño desafío que has publicado, así que aquí está mi solución. Supongo que todos sus archivos comienzan con 5 caracteres numéricos, así que use el comando de corte para reemplazar los archivos numéricos iniciales por "XXXXX".

A continuación, los archivos antes del comando.

-rw-rw-r--. 1 daniel daniel 0 May 13 23:18 11111_bar_file.csv
-rw-rw-r--. 1 daniel daniel 0 May 13 22:54 12345_baz_file.csv
-rw-rw-r--. 1 daniel daniel 0 May 13 22:54 67890_foo_file.xml

Debajo, el comando one liner.

for src in *.csv; do dst=XXXXX$(echo $src| cut -c6-); mv $src $dst; done;

A continuación, los archivos después del comando.

-rw-rw-r--. 1 daniel daniel 0 May 13 22:54 67890_foo_file.xml
-rw-rw-r--. 1 daniel daniel 0 May 13 22:54 XXXXX_bar_file.csv
-rw-rw-r--. 1 daniel daniel 0 May 13 23:18 XXXXX_baz_file.csv

¿Es eso lo que estás buscando? :)

Referencias

Recorriendo la salida del comando en bash

Subcadenas en bash

danieldeveloper001
fuente
2
Bash puede hacer este tipo de manipulación de cadenas, no es necesario bifurcar un nuevo proceso para cada uno, por favor, la otra respuesta sobre cómo.
chx
1
@chx, ya vi las otras respuestas y adquirí un poco de conocimiento, pero gracias por señalarlas. ¿Podría por favor dar más detalles no need to fork a new process for each?
danieldeveloper001
3
cutes un binario separado ( /usr/bin/cut) y su ejecución consume más recursos que el uso de complementos integrados de shell
chx
2
Ya veo, en realidad importa si la intención es renombrar muchos archivos. ¡Gracias por la aclaración!
danieldeveloper001
1

sin horquillas:

ls | perl -lne '$suf=substr($_,6); rename $_, "XXXXX-$suf"'

Cuando usa un bucle de shell, los mvtenedores una vez por archivo. El renamecomando de Perl no.

(El comando de cambio de nombre de Perl tiene algunas restricciones, pero en este caso específico esas restricciones no se aplican).

En cuanto al renamecomando que se mostró anteriormente, sí, eso funciona, pero entonces tienes toda esa confusión entre dos tipos diferentes de cambio de nombre, etc. Si tienes el correcto, genial, pero si no, esto también funciona.

Si no tiene el comando perl-rename y no puede instalarlo, simplemente puede hacer esto:

ls | perl -lne '$old=$_; s/(\w+)/XXXXX/; rename $old, $_'

Como puede ver, esto usa la misma sustitución que se muestra en la respuesta superior. Por supuesto, el cambio de nombre de perl tiene otras campanas y silbatos (la respuesta principal -nya se mencionó, luego está -0, -fy así sucesivamente), y cuanto más necesites, más deberías instalar eso en lugar de rodar el tuyo de esta manera .

sitaram
fuente
Las implementaciones habituales de una tubería tendrán horquillas.
muru
Quise decir, "no se bifurcará una vez por nombre de archivo", a diferencia de incluso shell, donde "mv" se bifurca / usr / bin / mv o lo que sea. Esto se debe a que el comando "rename" es un comando interno perl que llama directamente a rename () en libc. Por supuesto, tiene algunas restricciones, pero en este ejemplo específico esas restricciones no se aplican.
sitaram
1
Eso también es cierto para el renamecomando ( respuesta principal , también usa Perl), por lo que tal vez debería agregar un poco más de explicación que simplemente "sin tenedores" a la respuesta.
muru