¿Cómo cambiar el nombre de varios archivos reemplazando la cadena en el nombre del archivo? esta cadena contiene un "#"


43

https://serverfault.com/questions/70939/how-to-replace-a-text-string-in-multiple-files-in-linux

https://serverfault.com/questions/228733/how-to-rename-multiple-files-by-replacing-word-in-file-name

https://serverfault.com/questions/212153/replace-string-in-files-with-certain-file-extension

https://serverfault.com/questions/33158/searching-a-number-of-files-for-a-string-in-linux

Estos artículos mencionados han respondido a mi pregunta. Sin embargo, ninguno de ellos funciona para mí. Sospecho que es porque la cadena que estoy tratando de reemplazar tiene un # en ella. ¿Hay alguna forma especial de abordar esto?

Tengo un archivo de imagen que tuvo un é reemplazado por # U00a9 durante una migración del sitio. Estos se ven así:

Lucky-#U00a9NBC-80x60.jpg
Lucky-#U00a9NBC-125x125.jpg
Lucky-#U00a9NBC-150x150.jpg
Lucky-#U00a9NBC-250x250.jpg
Lucky-#U00a9NBC-282x232.jpg
Lucky-#U00a9NBC-300x150.jpg
Lucky-#U00a9NBC-300x200.jpg
Lucky-#U00a9NBC-300x250.jpg
Lucky-#U00a9NBC-360x240.jpg
Lucky-#U00a9NBC-400x250.jpg
Lucky-#U00a9NBC-430x270.jpg
Lucky-#U00a9NBC-480x240.jpg
Lucky-#U00a9NBC-600x240.jpg
Lucky-#U00a9NBC-600x250.jpg
Lucky-#U00a9NBC.jpg

y quiero cambiarlo a algo como esto:

Lucky-safeNBC-80x60.jpg
Lucky-safeNBC-125x125.jpg
Lucky-safeNBC-150x150.jpg
Lucky-safeNBC-250x250.jpg
Lucky-safeNBC-282x232.jpg
Lucky-safeNBC-300x150.jpg
Lucky-safeNBC-300x200.jpg
Lucky-safeNBC-300x250.jpg
Lucky-safeNBC-360x240.jpg
Lucky-safeNBC-400x250.jpg
Lucky-safeNBC-430x270.jpg
Lucky-safeNBC-480x240.jpg
Lucky-safeNBC-600x240.jpg
Lucky-safeNBC-600x250.jpg
Lucky-safeNBC.jpg

ACTUALIZAR:

Todos estos ejemplos comienzan con "LU00a9ucky pero aquí hay muchas imágenes con diferentes nombres. Simplemente estoy apuntando a la parte" # U00a9 "de la cadena para reemplazarla por" segura ".


3
Entonces, ¿qué has intentado realmente? Veo que se ha vinculado a algunas preguntas y dice que fallaron, pero ¿cómo fallaron? En mi opinión, el mejor ejemplo utiliza el renamecomando. Sospecho que tu cambio de nombre sería tan simple como rename -n 's/#/safeNBC/' *.jpg.
— Zoredache

Lo intenté rename -n 's/#U00a9/safe/' *.jpgy el comando fue aceptado pero no se produjeron cambios.

Claro, como habrás visto en la documentación que seguramente revisaste, esta -nes la no actopción. Lo que le permite ver si funciona antes de usarlo realmente. ¿La salida en la pantalla muestra los posibles nombres nuevos correctamente?
— Zoredache

Pido disculpas por haber copiado y pegado su ejemplo sin prestarle atención, hice el comando de cambio de nombre sin el -n. Creo que @DTK solucionó el problema, no estaba escapando del #.

Reemplazo de cadenas en nombres de archivos en MacOS: superuser.com/questions/152627/…
— Anton Tarasenko

Respuestas:


65

Para reemplazar #por somethingelsenombres de archivo en el directorio actual (no recursivo) puede usar la utilidad de cambio de nombre GNU :

rename  's/#/somethingelse/' *

Los personajes como -deben escapar con a \.

Para su caso, desearía usar

rename 's/#U00a9/safe/g' *

Tenga en cuenta que si solo desea operar en una determinada selección de archivos, por ejemplo, solo *.jpg, ajuste la entrada final para que coincida con esa selección:

rename 's/#U00a9/safe/g' *.jpg

Para realizar una prueba antes de cambiar realmente los nombres de archivo, use la -nbandera:

demo/> ls                               
Lucky-#U00a9NBC-125x125.jpg  
Lucky-#U00a9NBC-150x150.jpg 

demo/> rename -n 's/#U00a9/safe/g' *.jpg
rename(Lucky-#U00a9NBC-125x125.jpg, Lucky-safeNBC-125x125.jpg)
rename(Lucky-#U00a9NBC-150x150.jpg, Lucky-safeNBC-150x150.jpg)

Para OS X, GNU cambio de nombre se puede instalar utilizando homebrew : brew install rename.


Esto no funcionó en mi máquina (Arch Linux), pero la respuesta de mik sí.
— marcvangend

@marcvangend ¿Qué versión de renameestás usando? # sudo pacman -S perl-renameinstalará la versión perl, que es más potente y podría ser suficiente para que esta respuesta funcione para usted.
— John Gowers

@JohnGowers ¡Gracias! No me di cuenta de que hay dos versiones. En mi sistema, rename --versionregresa , rename from util-linux 2.29.2por lo que esa no es la versión perl.
— marcvangend

55
Hay dos renameutilidades comunes, pero ninguna de ellas está desarrollada por GNU: las distribuciones basadas en Debian incluyen una renameutilidad con su paquete Perl, mientras que las distribuciones basadas en Red Hat usan la renameutilidad de la util-linuxOrganización Kernel de Linux. Su enlace es a la funciónrename C de la biblioteca estándar GNU.
— Anthony G - justicia para Monica

2
En esta respuesta, ¿por qué tenemos que escribir /genrename 's/#U00a9/safe/g' *
— Nikhil

24

encuentre la lista de archivos y luego reemplace la palabra clave. a continuación se muestra un ejemplo

find . -name '*jpg' -exec bash -c ' mv $0 ${0/\#U00a9NBC/safeNBC}' {} \;

1
Necesitas algunas comillas dobles alrededor de tus mvargumentos, en caso de que haya espacios en el nombre
— deja de dañar a Monica el

Necesitaba reemplazar todos los archivos * _spec.rb a * _controller_spec.rb y su solución funcionó para mí. Gracias
— Jedi

Gracias. Esto resuelve mi problema
— Fabio Souza

19

Esto no es difícil, simplemente asegúrese de escapar del octothorpe (#) en el nombre anteponiendo una barra invertida (\).

find . -type f -name 'Lucky-*' | while read FILE ; do
    newfile="$(echo ${FILE} |sed -e 's/\\#U00a9/safe/')" ;
    mv "${FILE}" "${newfile}" ;
done 

Tu explicación tiene sentido, escapar de los #sonidos como lo que necesito. No veo una barra diagonal inversa en su ejemplo. Debería verse así: s/\#U00a9/safe/

@LeonFrancisShelhamer buena captura. Se tragó la barra invertida. Voy a modificar

17

Para escapar #del shell, solo use comillas simples ( '#'), comillas dobles ( "#") o barra invertida ( \#).

Lo más simple en su caso sería usar el renamecomando (si está disponible):

rename '#U00a9' safe *.jpg

2
Gracias. Si bien la respuesta más votada ( rename 's/#/somethingelse/' *) no funcionó en mi máquina (Arch Linux), esta sí.
— marcvangend

1
Esto funciona usando el comando rename de util-linux.
— inmaculado

10

no estoy seguro de cómo hacerlo, pero puedes probar esto en un bash shell:

for f in Lucky-#U00a9NBC-*.jpg; do mv -v "$f" "${f/#U00a9/safe}"; done;

explicación:

  1. recorre todos los nombres de archivo que coinciden con el glob (Lucky- # U00a9NBC - *. jpg)
  2. cambia el nombre del archivo con el comando mover (mv)
  3. utiliza la sustitución de parámetros bash nativos $ {var / Pattern / Replacement} para crear el nuevo nombre ("$ {f / # U00a9 / safe}")

Más información sobre la sustitución de parámetros (que es una OMI altamente infrautilizada): http://www.tldp.org/LDP/abs/html/parameter-substitution.html


Si bien este código puede responder la pregunta, no es muy útil por sí solo. Explicar cómo resuelve el problema mejoraría la utilidad y el valor a largo plazo de la respuesta.
— Anthony G - justicia para Mónica

Explicación explicativa agregada y lecturas adicionales según el comentario de Anthony.
— Gregory Patmore

1

Los ejemplos anteriores no funcionaban en mi sistema (CentOS 5.6), así que encontré un comando (posiblemente más específico del sistema) que funciona (nota: necesita escapar '#' con \en la línea de comando)

rename \#U00a9 safe *.jpg

[Además: todavía no tengo suficiente reputación para comentar, así que en respuesta a la pregunta de Nikhil sobre el uso de /gin rename 's/old_string/new_string/g'(planteado en los comentarios para otra respuesta anterior):

Use el gmodificador para realizar una sustitución 'global' (es decir, para sustituir new_string por old_string tantas veces como old_string ocurra). Esto no debería ser necesario en mi respuesta porque renamese aplicará a todos los archivos especificados con *. Consulte https://www.computerhope.com/unix/rename.htm para obtener una explicación concisa de este y otros modificadores.]


Correcto; Los sistemas operativos derivados de Fedora como CentOS tienen una versión diferente de los renamesistemas operativos derivados de Debian. Ver unix.stackexchange.com/a/238862/135943 . Y, por cierto, CentOS 5.6 es bastante antiguo y le recomiendo que actualice.
— Comodín el

Ah, gracias por la explicación + enlace. El sistema operativo obsoleto funciona y, por lo tanto, no depende de mí actualizar :) pero se está creando un nuevo clúster y presumiblemente lo actualizaremos cuando nos traslademos ...
— Ezra Citron

0

Aquí está la solución de DTK envuelta en la función bash reutilizable:

function renameFilesRecursively () {

  SEARCH_PATH="$1"
  SEARCH="$2"
  REPLACE="$3"

  find ${SEARCH_PATH} -type f -name "*${SEARCH}*" | while read FILENAME ; do
      NEW_FILENAME="$(echo ${FILENAME} | sed -e "s/${SEARCH}/${REPLACE}/g")";
      mv "${FILENAME}" "${NEW_FILENAME}";
  done

}

Así es como puedes usarlo:

renameFilesRecursively /home/user/my-files apple orange

0

En realidad renametiene una opción exactamente para eso llamado --substo -sen resumen. No es necesario utilizar la sintaxis de expresiones regulares.

rename -s '#U00a9' 'safe' *

Si desea reemplazar / sustituir múltiples ocurrencias, use --subst-allo -S.

Por cierto, solo quería reemplazar una cadena por nada (eliminarla del nombre del archivo) ... bueno, también tenemos una opción para ello -d/--deletey -D/--delete-all:

rename -d '#U00a9' *

-1

Otra opción es usar pyRenamer, una aplicación hecha específicamente para renombrar lotes.

Se puede instalar con sudo apt-get install pyrenamer

Para obtener detalles de uso, consulte su archivo README en GitHub .


1
Si realmente cree que esto podría responder la pregunta, agregue alguna explicación a su respuesta. Por sí solo, solo instala un paquete. Debe explicar lo que hace el comando y proporcionar un ejemplo que maneje los requisitos específicos del OP.
— roaima
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.