Basado en patrón, renombrar archivo por lotes en terminal

48

Necesito cambiar el nombre de lo siguiente:

file_001_loremipsum.png
file_002_dolor.png
file_003_sit.png
file_004_amet.png
file_105_randomness.png

dentro

upl_loremipsum.png
upl_dolor.png
upl_sit.png
upl_amet.png
upl_randomness.png

¿Cómo hago que suceda con solo una línea simple de comando de terminal?

Unamata Sanatarai
fuente
1
Una versión de Python a prueba de fallos basada en expresiones regulares que funciona de forma recursiva en todas las subcarpetas: stackoverflow.com/a/39698169/191246
ccpizza

Respuestas:

79

La solución al ejemplo anterior, usando rename :

rename -v -n 's/file_\d{1,3}/upl/' file_*.png

Uso:

rename [options] [Perl regex search/replace expression] [files]

De man rename:

   -v, --verbose
           Verbose: print names of files successfully renamed.
   -n, --no-act
           No Action: show what files would have been renamed.

rename PUEDE tomar regex como argumentos.

Lo que estamos viendo es el contenido entre las comillas simples '. Puede colocar expresiones regulares separadas por /.

Fórmula: s/(1)/(2)/where (1)= patrón de búsqueda y (2)= patrón de reemplazo.

Por lo tanto, familiarícese con expresiones regulares y disfrute del cambio de nombre de archivo por lotes basado en patrones.

Unamata Sanatarai
fuente
14
Sé que esto es Ubuntu, pero si alguien termina aquí a pesar de que estaban buscando una solución OS X (lo hice), renamese instala fácilmente con brew install rename.
Sandstrom
En Ubuntu 18.10, la --no-actbandera es en su --nonolugar. Esta respuesta también podría ser un poco más explícita: se [files]refiere a un archivo de coincidencia de patrón inicial en el directorio actual al que se quiere renombrar (por ejemplo, *coincide con todo, pero solo en el directorio actual).
Patrick Dark
Su enlace apunta a otro rename, que tiene formato rename from to filey no admite expresiones regulares. En realidad, mi distribución de Linux (Cent OS 7) tiene exactamente esa versión.
Alex Che
6

Si los archivos están en varios directorios, use renombrar después de una búsqueda como:

find -iname file_*.png -type f -exec rename -n 's/file_[0-9]{3}(.*\.png)/upl$1/' {} \;

el -n después de cambiar el nombre es para probar, eliminarlo para continuar! -)

así, asocias encontrar y renombrar poder.

Personalmente, lo usé para cambiar el nombre del encabezado de fuentes .h a .hpp

find -iname *.h -type f -exec rename 's/(.*\.)h/$1hpp/' {} \;
bcag2
fuente
Hay documentación para el -iname, -typey -execbanderas a manpages.ubuntu.com/manpages/bionic/man1/find.1.html#expression . ( find --helpno es particularmente útil para este comando). TL; DR: -inamecoincide con un patrón que no distingue entre mayúsculas y minúsculas; -type fcoincide con "archivos normales"; y -execejecuta una expresión hasta que encuentra un carácter ;(punto y coma).
Patrick Dark
5

¡Esto se puede hacer con poca magia de expansión de parámetros bash!

for f in file_[0-9]*_*; do mv $f upl_${f#file_[0-9]*_}; done

file_[0-9]*_*;- El primer patrón se usa para recorrer todos los archivos que comienzan con 'file_anynumber_'
${f#file_[0-9]*_}- El segundo patrón file_[0-9]*_se usa en la expansión de parámetros que le dice a bash que elimine 'file_anynumber_' del comienzo de la cadena.

Para más información sobre Parameter expansion:

man bash
Basharat Sialvi
fuente
Tenga en cuenta que esto usa globos, no expresiones regulares, por [0-9]*lo que coincidirá con un dígito seguido de cualquier cadena. Probablemente haya una mejor manera de unir solo números, pero no se me ocurre nada sucinto.
wjandrea
¿También podría sugerir una forma de hacer que este comando funcione de forma recursiva en todos los subdirectorios?
Francesco DM