¿Cómo cambiar el nombre de archivos por lotes en una terminal macOS?

123

Tengo una carpeta con una serie de archivos llamados:

prefix_1234_567.png
prefix_abcd_efg.png

Me gustaría eliminar por lotes un guión bajo y el contenido medio para que el resultado sea:

prefix_567.png
prefix_efg.png

Relevante pero no completamente explicativo:

Kidnim
fuente
mire los métodos de rango y subcadena de NSString y NSMutableString
Grady Player
1
¿Ha considerado soluciones no terminales para esto? Un flujo de trabajo de Automator puede realizar este tipo de operaciones con facilidad. Puede crear un flujo de trabajo automático para cambiar el nombre de todos los archivos y reemplazar el texto _*_con un espacio en blanco.
Encriptado
pensé que el automator no podía hacer comodines
kidnim

Respuestas:

234

En su caso específico, puede usar el siguiente bashcomando ( bashes el shell predeterminado en macOS):

for f in *.png; do echo mv "$f" "${f/_*_/_}"; done

Nota: Si existe la posibilidad de que sus nombres de archivo comiencen con -, coloque -- antes de ellos [1]:
mv -- "$f" "${f/_*_/_}"

Nota: echose antepone a mvpara realizar un ensayo. Elimínelo para realizar un cambio de nombre real.

Puede ejecutarlo desde la línea de comandos o usarlo en un script.

  • "${f/_*_/_}"es una aplicación de bash expansión de parámetros : el (primer) patrón de coincidencia de subcadenas _*_se reemplaza con literal _, cortando efectivamente el token del medio del nombre.
  • Tenga en cuenta que _*_es un patrón (una expresión comodín, como también se usa para globbing), no una expresión regular (para aprender sobre patrones, ejecutar man bashy buscar Pattern Matching).

Si tiene que cambiar el nombre de los archivos por lotes con frecuencia, considere instalar una herramienta especializada como la renameutilidad basada en Perl . En macOS, puede instalarlo utilizando el popular administrador de paquetes Homebrew de la siguiente manera:

brew install rename

Aquí está el equivalente del comando en la parte superior usando rename:

rename -n -e 's/_.*_/_/'  *.png

Nuevamente, este comando realiza una ejecución en seco; eliminar -npara realizar el cambio de nombre real.

  • De forma similar a la bashsolución, s/.../.../realiza la sustitución de texto, pero, a diferencia de lo que bashocurre con las expresiones regulares verdaderas, se utilizan.

[1] El propósito de argumento especial --, que está soportado por la mayoría de los servicios públicos, es de señalar que los argumentos posteriores deben ser tratados como los operandos (valores), incluso si se ven como opciones debido a que empiecen con -, como Jacob C. notas.

mklement0
fuente
3
gran respuesta, funcionó perfectamente. También agradezco que haya vuelto y lo haya editado para explicarlo más y proporcionar una solución más elegante si repito esto. de nuevo, muchas gracias, muy útil
kidnim
4
Un ejemplo que utiliza reemplazos coincidentes ( .*-> $1), por ejemplo, cambiar el nombre Foo bar S01E01 biz baz.exta S01E01.ext:rename -n -e 's/.*(S[0-9]{2}E[0-9]{2}).*(\.[a-z]{2,4})/$1$2/' *
Steve Robbins
2
Me encanta la idea de usarlo echopara carreras en seco. ¡Gracias por el consejo!
James Wright
Recomiendo encarecidamente hacer elbrew install rename
Chris Redford
98

Para cambiar el nombre de los archivos, puede utilizar la renameutilidad:

brew install rename

Por ejemplo, para cambiar una cadena de búsqueda en todos los nombres de archivo en el directorio actual:

rename -nvs searchword replaceword *

Elimine el parámetro 'n' para aplicar los cambios.

Más información: man rename

David Thomas
fuente
1
OS Xlas versiones de GNU bash( x86_64-apple-darwin ) no incluyen la utilidad de cambio de nombre.
l'L'l
4
Gracias, sí, debe instalarse a través debrew install rename
David Thomas
2
¡Este consejo es genial! He escrito rename -vs GLYCOPHORIN GLYCC *y ahora es cambiar el nombre de archivos de forma automática 450+. Y super rápido también.
Sander W.van der Laan
3
¡Excelente! Me encanta la parte de "mostrar lo que se cambiaría" ANTES de que cambie el nombre de las cosas.
Ben Duffin
3
También puede usar una expresión regular. renombrar 's / 123 / onetwothree / g' *
Bryan
12

Podrías usar sed:

ls * | sed -e 'p;s@_.*_@_@g' | xargs -n2 mv

resultado:

prefix_567.png prefix_efg.png

* para hacer un ensayo primero, reemplace mval final conecho

Explicación:

  • e: opcional para solo 1 comando sed.
  • p: para imprimir la entrada en sed, en este caso será el nombre del archivo original antes de cualquier cambio de nombre
  • @: es un reemplazo del carácter / para hacer que sed sea más legible. Es decir, en lugar de usar sed s / search / replace / g, use s @ search @ replace @ g
  • _. *: el guión bajo es un carácter de escape para referirse al '.' real carácter cero o más veces (a diferencia de CUALQUIER carácter en regex)
  • -n2: indica que hay 2 salidas que deben pasarse a mv como parámetros. para cada entrada de ls , este comando sed generará 2 salidas, que luego se suministrarán a mv.
l'l'l
fuente
1
Solución inteligente, aunque algo misteriosa. Hacer esto más general, para admitir también nombres de archivo con espacios incrustados, se vuelve aún más arcano: ls * | xargs -I % bash -c 'echo mv "%" "$(sed 's@_.*_@_@' <<<"%")"'(eliminar echopara cambiar el nombre).
mklement0
2
¿Arcano? ¡Me encanta esto!
Bilal Akil
7

Tenía un lote de archivos que se veía así: be90-01.png y necesitaba cambiar el guión para subrayar. Usé esto, que funcionó bien:

for f in *; do mv "$f" "`echo $f | tr '-' '_'`"; done
JanB
fuente
2

puede instalar el renamecomando usando brew. solo hazlo brew install renamey úsalo.

Nisim Joseph
fuente
1

Utilizando mmv

mmv '*_*_*' '#1_#3' *.png
αғsнιη
fuente
necesita instalar primero sudo apt-get install mmv.
αғsнιη
1
Dado que se trataba de OS X, el procedimiento de instalación correcto es brew install mmv.
buckaroo1177125
1

prueba esto

for i in *.png ; do mv "$i" "${i/remove_me*.png/.png}" ; done

Aquí hay otra forma:

for file in Name*.png; do mv "$file" "01_$file"; done
Thiago
fuente