Cambie el nombre de varios archivos usando secuencias de comandos Bash

Quiero cambiar el nombre de varios archivos en el mismo directorio usando secuencias de comandos Bash. Los nombres de los archivos son los siguientes:

file2602201409853.p file0901201437404.p file0901201438761.p file1003201410069.p file2602201410180.p 

Quiero cambiar el nombre al siguiente formato:

file2503201409853.p file2503201437404.p file2503201438761.p file2503201410069.p file2503201410180.p 

Estaba leyendo sobre el comando de cambio de nombre y trato de hacerlo de esta manera, pero no hace nada, creo que tengo preguntas sobre la sintaxis. Luego leí que puedes hacer un bucle usando el comando mv de la siguiente manera:

for file in cmpsms*2014*.p; do mv "$file" "${file/cmpsms*2014*.p/cmpsms25032014*.p}" done 

Pero no puedo cambiar el nombre de los archivos. ¿Qué estoy haciendo mal?

Comentarios

  • posible duplicado de ¿Cómo puedo cambiar el nombre de muchas cosas? de archivos que usan una expresión regular?
  • No puede ' t tener una expresión de patrón en el lado derecho de una expresión de reemplazo de expansión de parámetro. ¿Qué esperabas que estuviera donde está ese *?
  • @Kiwy Esa pregunta se trata de eliminar una parte del nombre del archivo. Ergo, es muy dudoso que lo duplique.
  • La próxima vez, describa los cambios de nombre de archivo que desea hacer (tuve que mirar esto durante un tiempo antes de ver las diferencias y similitudes). Los ejemplos son buenos, pero una descripción así como ejemplos es aún mejor.

Respuesta

Hizo bien en considerar cambiar el nombre primero. La sintaxis es un poco extraña si no está acostumbrado a las expresiones regulares, pero es, con mucho, la ruta más rápida / corta una vez que sabe lo que está haciendo:

rename "s/\d{4}/2503/" file* 

Eso simplemente coincide con los primeros 4 números y los cambia por los que usted especificó.

Y un arnés de prueba (-vn significa ser detallado pero no hacer cualquier cosa) usando sus nombres de archivo:

$ rename "s/\d{4}/2503/" file* -vn file0901201437404.p renamed as file2503201437404.p file0901201438761.p renamed as file2503201438761.p file1003201410069.p renamed as file2503201410069.p file2602201409853.p renamed as file2503201409853.p file2602201410180.p renamed as file2503201410180.p 

Comentarios

  • Nota que este es el cambio de nombre de Perl en Debian y derivados (Ubuntu, Mint,…). En otras distribuciones de Linux, rename es una herramienta de cambio de nombre de archivos completamente diferente (que Debian incluye como rename.ul).
  • Si su falta distributiva de dicha herramienta, mire la respuesta de @Michael Campbell. Creo que todos los distributivos reemplazan el valor predeterminado rename como lo hizo Debian.

Respuesta

Esto debería funcionar:

for f in file*; do mv $f ${f/${f:4:8}/25032014}; done 

Reemplaza la cadena entre el cuarto y el duodécimo carácter por «25032014».

Comentarios

  • esto for f in file*; do mv $f ${f/${f:4:4}/2503}; done también funciona.
  • Eso ' s agradable. Si solo desea reemplazar una palabra por palabra, funciona como sed. p.ej. for f in *Huge*; do mv $f ${f/Huge/Monstrous}; done
  • @Eric: publiqué tu respuesta como alternativa porque creo que es ' más clara y elegante . Si también desea publicarlo como respuesta, ' eliminaré el mío. ¡Gracias!
  • ¿Por qué faltan comillas dobles ?
  • Me da un error: " mv: target ' FILE_NAME ' no es un directorio "

Respuesta

Esta es realmente la respuesta de @Eric desde arriba, pero es una respuesta elegante, así que Lo voy a publicar como una respuesta adecuada para llamar más la atención sobre él.

for f in *Huge*; do mv "$f" "${f/Huge/Monstrous}"; done 

Respuesta

ptrn="file[0-9][0-9][0-9][0-9]2014[0-9][0-9][0-9][0-9][0-9].p" path=/dir ( set -- "${path}/"${ptrn} ; for f ; do { echo "mv ${path}/${f} \ ${path}/file25032014${f#2014}" } ; done ) 

Esto debería funcionar. Nota: no tengo el hábito de entregar comandos mv en masa, como está escrito, es solo un eco. Tú» tendré que resolver eso antes de que funcione.

Respuesta

Una forma nativa simple de hacerlo sin bucles, con recorrido de directorio :

find -type f | xargs -I {} mv {} {}.txt 

Cambiará el nombre cada archivo en su lugar.

Y debajo de un trabajo ejemplo con paralelización :

find -name "file*.p" | parallel "f="{}" ; mv -- {} ${f:0:4}2503${f:8}" 

Comentarios

  • Fue un primer enfoque fácil para imaginar una mejor solución. Si desea un comando que funcione, haga:
  • find -type f -name "file*.p" | parallel 'ext="{}" ; mv -- {} ${ext:0:4}2503${ext:8}'

Responder

Si encuentra que hace mucho este tipo de cosas, busque «rename.pl». Es un script de Perl, pero le permite simplemente alimentarlo con código Perl (como una expresión ///), y hará un cambio de nombre masivo basado en esa expresión o código.

Existe una versión básica aquí: http://stackoverflow.org/wiki/Rename.pl pero hay otras versiones flotando en la red. Ha existido durante siglos y siglos.

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *