¿Cómo cambiar el nombre de varios archivos reemplazando la palabra en el nombre del archivo?

36

Reemplace ACDC a AC-DC

Por ejemplo tenemos estos archivos

ACDC - Rock N 'Roll no es contaminación acústica.xxx

ACDC - Rocker.xxx

ACDC - Dispara a la emoción.xxx

Quiero que se conviertan en:

AC-DC - Rock N 'Roll no es contaminación acústica.xxx

AC-DC - Rocker.xxx

AC-DC - Dispara a la emoción.xxx

Sé que sed o awk se usa para esta operación. No puedo buscar en Google nada, así que le pido su ayuda =) ¿Podría proporcionar un comando de shell de trabajo completo para esta tarea?

Comentarios: solución para usuarios de OSX

holms
fuente
1
Siento que hay una pregunta más grande aquí: ¿estás tratando de arreglar los nombres de archivos mp3 en general? Hay varios guiones que la gente ha escrito a lo largo de los años para hacer esto. Creo que uno que he usado se llamaba mp3fixer.
Phil Hollenback
no, no es acerca de mp3 sólo tengo que gestionar algunos archivos de gran tamaño con nombres similares, y algo que todo debe ser reemplazado o fijo situación común ... así que necesito esta solución ingeniosa para cambiar el nombre de todos ellos
holms

Respuestas:

45
rename 's/ACDC/AC-DC/' *.xxx

desde man rename

DESCRIPTION
       "rename" renames the filenames supplied according to the rule specified as the 
first argument.  The perlexpr argument is a Perl expression which is expected to modify the 
$_ string in Perl for at least some of the filenames specified.  If a given filename is not 
modified by the expression, it will not be renamed.  If no filenames are given on
           the command line, filenames will be read via standard input.

Por ejemplo, para cambiar el nombre de todos los archivos que coinciden con "* .bak" para quitar la extensión, puede decir

rename 's/\.bak$//' *.bak

Para traducir nombres en mayúsculas a inferiores, usaría

rename 'y/A-Z/a-z/' *
Joel K
fuente
55
Tenga en cuenta que muchas máquinas Linux vienen con cambio de nombre de util-linux, que implementa una sustitución simple, no expresiones regulares. Entonces, si el cambio de nombre falla en silencio sin hacer nada, probablemente esté usando el error rename.
Phil Hollenback
¡Estuve buscando esto por años! gracias!
Holms
@PhilHollenback ¿Cómo encontrar / instalar el correcto entonces? :)
Henry
No funciona cuando tengo guiones bajos en mis nombres de archivo en lugar de espacios, ¿cómo puedo resolver eso?
unfa
13

Esta respuesta contiene las partes buenas de todas las otras respuestas, mientras que deja de lado la herejía ls | while read.

Directorio actual:

for file in ACDC*.xxx; do
    mv "$file" "${file//ACDC/AC-DC}"
done

Incluyendo subdirectorios:

find . -type f -name "ACDC*" -print0 | while read -r -d '' file; do
    mv "$file" "${file//ACDC/AC-DC}"
done

Es muy poco probable que los caracteres de nueva línea estén en nombres de archivo, por lo que esto puede ser más simple mientras se trabaja con nombres que contienen espacios:

find . -type f -name "ACDC*" | while read -r file; do
    mv "$file" "${file//ACDC/AC-DC}"
done
Gravedad
fuente
9

Para usar la versión util-linux de la renameque Phil se refirió (en Ubuntu, se llama rename.ul):

rename ACDC AC-DC ACDC*

o

rename.ul ACDC AC-DC ACDC*
Pausado hasta nuevo aviso.
fuente
1
su variante es la mejor =) tantos artículos estúpidos en google sobre find and send and awk ... a esta operación simple para la cual renameutils egxist ya!
holms
4

Usando el shell bash

find . -type f -name "ACDC*" -print0 | while read -d $'\0' f
do
   new=`echo "$f" | sed -e "s/ACDC/AC-DC/"`
   mv "$f" "$new"
done

Nota: el uso findprocesará el directorio actual y los directorios bajo.

Ø de anillo
fuente
1

Depende de tu caparazón. En zsh, haría esto:

for file in ACDC*.xxx; do
    mv "$file" "$(echo $file | sed -e 's/ACDC/AC-DC/')"
done

Probablemente no sea la mejor solución, pero funciona.

polemon
fuente
1

Usando bash:

ls *.xxx | while read fn; do
    mv "${fn}" "${fn/ACDC/AC-DC}";
done

Si tienes el renameprograma instalado:

rename 's/ACDC/AC-DC/' *.xxx
ThatGraemeGuy
fuente