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
.