¿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 ".

Comunidad
fuente
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.

KrisWebDev
fuente
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}' {} \;
Sujit Dhamale
fuente
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 
Comunidad
fuente
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
mik
fuente
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

Gregory Patmore
fuente
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.]

Ezra Citron
fuente
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
Slava Fomin II
fuente
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' *
lapin
fuente
-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 .

Sajna T
fuente
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