Encontrar múltiples archivos de forma recursiva y cambiar el nombre en Linux

Tengo archivos como a_dbg.txt, b_dbg.txt ... en un sistema Suse 10 . Quiero escribir un script de shell bash que debería cambiar el nombre de estos archivos eliminando “_dbg” de ellos.

Google me sugirió usar el comando de rename . Así que rename _dbg.txt .txt *dbg* el comando rename _dbg.txt .txt *dbg* en la CURRENT_FOLDER

Mi actual CURRENT_FOLDER contiene los siguientes archivos.

 CURRENT_FOLDER/a_dbg.txt CURRENT_FOLDER/b_dbg.txt CURRENT_FOLDER/XX/c_dbg.txt CURRENT_FOLDER/YY/d_dbg.txt 

Después de ejecutar el comando de rename ,

 CURRENT_FOLDER/a.txt CURRENT_FOLDER/b.txt CURRENT_FOLDER/XX/c_dbg.txt CURRENT_FOLDER/YY/d_dbg.txt 

No está haciendo de manera recursiva, cómo hacer que este comando cambie el nombre de los archivos en todos los subdirectorios. Como XX y YY tendré tantos subdirectorios cuyo nombre es impredecible. Y también mi CURRENT_FOLDER tendrá algunos otros archivos también.

Puede usar find para encontrar todos los archivos coincidentes recursivamente:

 $ find . -iname "*dbg*" -exec rename _dbg.txt .txt '{}' \; 

EDITAR: qué '{}' y \; ¿son?

El argumento -exec hace que find ejecute un rename de rename para cada archivo coincidente encontrado. '{}' se reemplazará por el nombre de ruta del archivo. El último token, \; está allí solo para marcar el final de la expresión del ejecutivo.

Todo lo que se describe muy bien en la página del manual para encontrar:

  -exec utility [argument ...] ; True if the program named utility returns a zero value as its exit status. Optional arguments may be passed to the utility. The expression must be terminated by a semicolon (``;''). If you invoke find from a shell you may need to quote the semicolon if the shell would otherwise treat it as a control operator. If the string ``{}'' appears anywhere in the utility name or the argu- ments it is replaced by the pathname of the current file. Utility will be executed from the directory from which find was executed. Utility and arguments are not subject to the further expansion of shell patterns and constructs. 

pequeño script que escribí para reemplazar todos los archivos con la extensión .txt a la extensión .cpp en / tmp y subdirectorios recursivamente

 #!/bin/bash for file in $(find /tmp -name '*.txt') do mv $file $(echo "$file" | sed -r 's|.txt|.cpp|g') done 

con bash:

 shopt -s globstar nullglob rename _dbg.txt .txt **/*dbg* 

Para cambiar el nombre de forma recursiva, uso los siguientes comandos:

 find -iname \*.* | rename -v "s/ /-/g" 

Scipt arriba puede escribirse en una línea:

 find /tmp -name "*.txt" -exec bash -c 'mv $0 $(echo "$0" | sed -r \"s|.txt|.cpp|g\")' '{}' \; 

Si solo quieres cambiar el nombre y no te importa usar una herramienta externa, entonces puedes usar rnm . El comando sería:

 #on current folder rnm -dp -1 -fo -ssf '_dbg' -rs '/_dbg//' * 

-dp -1 lo hará recursivo para todos los subdirectorios.

-fo implica modo solo archivo.

-ssf '_dbg' busca archivos con _dbg en el nombre del archivo.

-rs '/_dbg//' reemplaza _dbg con cadena vacía.

Puede ejecutar el comando anterior con la ruta de CURRENT_FOLDER también:

 rnm -dp -1 -fo -ssf '_dbg' -rs '/_dbg//' /path/to/the/directory 

Puedes usar esto a continuación.

 rename --no-act 's/\.html$/\.php/' *.html */*.html 

solución clásica:

 for f in $(find . -name "*dbg*"); do mv $f $(echo $f | sed 's/_dbg//'); done