¿Cómo hacer más de un reemplazo de subcadena a la vez en bash?

Tengo un directorio que contiene archivos de imagen que deben repetirse en bash. Mientras repito, quiero reemplazar tanto el nombre del archivo como la extensión en el comando de una sola línea.

Archivos de ejemplo:

images/file_name_1.jpg images/file_name_2.jpg 

Normalmente, puedo hacer un solo reemplazo como este:

 for i in images/*; do echo ${i/file/image}; done  

Y la salida se convierte en:

 images/image_name_1.jpg images/image_name_2.jpg  

¿Cómo puedo mantenerlo en bucle for y reemplazar la cadena «jpg» por «png» también? Es solo una instancia, podría reemplazar el punto por una coma, etc.

Cuando intento esto:

 for i in images/*; do echo ${{i/jpg/png}/file/image}; done  

No funciona. No pude encontrar ninguna otra solución o idea. ¿Es esto posible? Si es así, ¿cómo?

Comentarios

  • No ' No sé por qué esto no ' no funcionó en bash, pero los reemplazos anidados funcionan como esperabas en zsh. Dependiendo de tu entorno, podrías considerar usar un mejor shell;)

Respuesta

El enfoque simple sería asignar el resultado a una variable, luego trabajar con esa variable. Ejemplo:

 for filename in images/* do echo "filename is now $filename" filename=${filename/jpg/png}; echo "filename is now $filename" filename=${filename/file/image}; echo "filename is now $filename" echo "final filename is ${filename}" done  

Comentarios

  • Esta respuesta no está completa. Las sustituciones se aplicarán en cualquier lugar de las cadenas de nombre de archivo. Según la pregunta, Kubilay desea reemplazar un prefijo y una extensión (sufijo). ¿Puede modificarlo y tenerlo en cuenta? : $ {var / # Patrón / Reemplazo} Si el prefijo de var coincide con el Patrón, sustituya Reemplazo por Patrón. $ {var /% Patrón / Reemplazo} Si el sufijo de var coincide con el Patrón, luego sustituya el Patrón por Reemplazo.
  • @rMistero No ' s no hay regla contra la publicación de otra respuesta solo porque una respuesta ha sido aceptada. De hecho, creo que debería hacerlo, especialmente porque la semántica de lo que propone es diferente. Dicho esto, esta es la forma de hacer lo que dijo el OP después de haberlo intentado, por lo que incluso si hay otros resultados que también podrían ser válidos, creo que es seguro asumir que esto está en línea con lo que el OP quería lograr.

Responder

Puede asignar el reemplazo anterior a una variable y ejecutar reemplazar en esa variable en su lugar

 for i in images/* do j=${i/jpg/png} echo ${j/file/image} done  

Comentarios

  • No estoy seguro si funciona. " para i en imágenes / *; hacer j = {i / jpg / png} echo $ {j / archivo / imagen}; hecho " repite " {i / jpg / png} " repetidamente.
  • Ahora sí: " para i en imágenes / *. jpg; hacer j = $ {i / jpg / png}; echo $ {j / archivo / imagen}; hecho ". ¡Gracias!

Responda

para cambiar cualquier cadena :

$ echo "images/file_name_1.jpg" | perl -pE "s/file/image/;s/jpg$/png/;" images/image_name_1.png 

un atajo para cambiar el nombre (que puede ser el objetivo final:

$ rename "s/file/image/;s/jpg$/png/;" "$i" 

Comentarios

  • Sigo pensando que invocar Perl una vez para cada archivo es excesivo, pero al menos ahora esto da una respuesta a la pregunta. 🙂
  • @MichaelKj ö rling No ' no necesita invocar Perl para cada archivo, puede hacerlo rename … images/*. Pero esto requiere una distribución basada en Debian (rename en otras variantes de Linux es un comando completamente diferente).
  • @Gilles Estaba pensando más en la primera versión, particularmente porque no hay ' nada en la pregunta sobre cómo cambiar el nombre de los archivos. La versión original (período de gracia editado) de esta respuesta solo tenía la sugerencia de comando rename.

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *