bash - texto - Buscar+reemplazar cadenas en nombres de archivos
sed reemplazar linea completa (2)
Ambas variaciones mostradas aquí funcionan correctamente en la estructura de prueba de OPs:
find . -depth -name ''*foo*'' -execdir bash -c ''mv -i "$1" "${1//foo/bar}"'' bash {} /;
o, si tiene una gran cantidad de archivos y desea que se ejecute más rápido:
find . -depth -name ''*foo*'' -execdir bash -c ''for f; do mv -i "$f" "${f//foo/bar}"; done'' bash {} +
EDITAR : Como se señaló en los comentarios, mi respuesta anterior utilizando un comando de find
que no usó la opción execdir
y el rename
tiene problemas para cambiar el nombre de los archivos en directorios que contienen foo en su nombre. Como se sugirió, he cambiado los comandos de búsqueda para usar -execdir
, y he eliminado la variación utilizando el comando rename
ya que no es un comando estándar.
Usando bash, ¿cómo puedo buscar todas las apariciones de la subcadena ''foo'' en todos los nombres de archivo (incluidas las carpetas) contenidos recursivamente en un directorio y reemplazarlos con ''barra''?
Por ejemplo, si la estructura actual se ve así:
-foo_test
- fooo.txt
- xfoo
- yfoo.h
- 1foo.c
Debería verse así después de ejecutar el script bash:
-bar_test
- baro.txt
- xbar
- ybar.h
- 1bar.c
Esto fue complicado debido a los nombres de directorio con varias instancias de "foo". Cuando cambia ./foo_test/xfoo
a ./bar_test/xbar
todo lo que estaba en ./foo_test
vuelve inaccesible. Así que primero cambié los nombres de archivo y luego cambié la última aparición de "foo" en los nombres de directorio. Agregué declaraciones de eco para rastrear lo que sucede durante el desarrollo. Usted puede, por supuesto, eliminarlos.
#!/bin/sh
#first change the file names
#append ''.'' to process files in current directory
for D in $(find -d . -name "*foo*" -type d ) ''.''
do
pushd $D >> /dev/null
echo ''directory: '' "$D"
for file in $(find . -name "*foo*" -type f -maxdepth 1)
do
echo '' change'' "$file" ''to'' `echo "$file" | sed s/foo/bar/g`
mv "$file" `echo "$file" | sed s/foo/bar/g`
done
popd >> /dev/null
done
echo ''''
#Now change the directory names
for D in $(find -d . -name "*foo*" -type d )
do
echo ''change'' "$D" ''to'' `echo "$D" | sed ''s//(.*/)foo//1bar/''`
#change only the last occurance of foo
mv "$D" `echo "$D" | sed ''s//(.*/)foo//1bar/''`
done
No tengo dudas de que hay formas más cortas y elegantes de hacerlo (probablemente solo eliminando la mitad de las líneas de este script), pero estoy bastante seguro de que esto funciona.
EDITAR Los bucles idénticos eran una bandera roja. Esta versión solo se repite una vez. Recibes un mensaje intentando mv ''.'' ''.''
mv ''.'' ''.''
, pero se ignora con seguridad.
#!/bin/sh
#first change the file names
#append ''.'' to change file in current directory
for D in $(find -d . -name "*foo*" -type d ) ''.''
do
pushd $D >> /dev/null
echo ''directory: '' "$D"
for file in $(find . -name "*foo*" -type f -maxdepth 1)
do
echo '' change'' "$file" ''to'' `echo "$file" | sed s/foo/bar/g`
mv "$file" `echo "$file" | sed s/foo/bar/g`
done
popd >> /dev/null
echo ''change'' "$D" ''to'' `echo "$D" | sed ''s//(.*/)foo//1bar/''`
#change only the last occurence of foo
mv "$D" `echo "$D" | sed ''s//(.*/)foo//1bar/''`
done