2010-12-22 23 views

Respuesta

59

rename es un poco peligroso, ya que según su página de manual:

de cambio de nombre se cambie el nombre de los archivos especificados mediante la sustitución de la primera aparición de ...

Con mucho gusto hará lo incorrecto con nombres de archivo como c.txt.parser.y.

Aquí es una solución utilizando find y bash:

find -type f -name '*.txt' | while read f; do mv "$f" "${f%.txt}"; done 

Tenga en cuenta que esto se romperá si un nombre de archivo contiene un salto de línea (raro, pero no imposible).

Si tiene GNU encontrar, esta es una solución más sólida:

find -type f -name '*.txt' -print0 | while read -d $'\0' f; do mv "$f" "${f%.txt}"; done 
+1

Eso es cierto con respecto a la versión 'util-linux-ng' de' rename', pero la versión de script Perl puede hacer 'rename 's/.txt $ //' * .txt' –

+0

para mí renombre 's/.txt $ // '* .txt no funcionó – rp101

+1

te falta actual "." en cuanto a la ubicación donde desea ejecutar. Tal vez esta es mi variante osx de find, o mi ruta no está configurada correctamente. – bgs

10

Puede pasar explícitamente una cadena vacía como argumento.

rename .old '' *.old

Y con subcarpetas, find . -type d -exec rename .old '' {}/*.old \;. {} es el sustituto de la entrada encontrada con find, y \; termina el arglist para el comando dado después de -exec.

1

Para subcarpetas:

for i in `find myfolder -type d`; do 
    rename .old .new $i/*.old 
done 
+2

Esto puede causar problemas si hay un nombre de carpeta con un espacio en él. – robert

15

utilizo este:

find ./ -name "*.old" -exec sh -c 'mv $0 `basename "$0" .old`.new' '{}' \; 
+0

gracias, no sabía esta sintaxis, y funciona también en MacOSX (que carece 'rename' nativo). – Utopik

+0

esto funciona muy bien en Windows Git Bash, gracias! – RaptoX

+0

Debería haber agregado el nombre del directorio en caso de que el destino esté en una subcarpeta: find ./ -name "* .old" -exec sh -c 'mv $ 0 'dirname" $ ​​0 "'/'nombre base" $ 0 ".old' .new '' {} '\; –

13

La versión Perl del cambio de nombre puede eliminar una extensión de la siguiente manera:

rename 's/\.txt$//' *.txt 

Esto se puede combinar con find para hacer también subcarpetas.

1

en el pescado, que puede hacer

for file in *.old 
     touch (basename "$file" .old).new 
end 
3

En caso de que ayuda, así es como lo hago con zsh:

for f in ./**/*.old; do 
    mv "${f}" "${f%.old}" 
done 

La construcción ${x%pattern} en zsh elimina la aparición más corta del pattern en el fin de $x.Aquí se abstrae como una función:

function chgext() { 
    local srcext=".old" 
    local dstext="" 
    local dir="." 

    [[ "$#" -ge 1 ]] && srcext="$1" 
    [[ "$#" -gt 2 ]] && dstext="$2" dir="$3" || dir="${2:-.}" 

    local bname='' 
    for f in "${dir}"/**/*"${srcext}"; do 
     bname="${f%${srcext}}" 
     echo "${bname}{${srcext} → ${dstext}}" 
     mv "${f}" "${bname}${dstext}" 
    done 
} 

Uso:

chgext 
chgext src 
chgext src dir 
chgext src dst dir 

Where `src` is the extension to find (default: ".old") 
     `dst` is the extension to replace with (default: "") 
     `dir` is the directory to act on (default: ".") 
Cuestiones relacionadas