file - recursivamente - renombrar lista de archivos linux
Renombra múltiples archivos en Unix (20)
Hay varios archivos en un directorio que comienzan con el prefijo fgh
, por ejemplo:
fghfilea
fghfileb
fghfilec
Quiero cambiar el nombre de todos para comenzar con el prefijo jkl
. ¿Hay un solo comando para hacer eso en lugar de renombrar cada archivo individualmente?
Aquí hay una forma de hacerlo usando la línea de comandos Groovy:
groovy -e ''new File(".").eachFileMatch(~/fgh.*/) {it.renameTo(it.name.replaceFirst("fgh", "jkl"))}''
Así es como sed
y mv
se pueden usar juntos para cambiar el nombre:
for f in fgh*; do mv "$f" $(echo "$f" | sed ''s/^fgh/jkl/g''); done
Según el comentario a continuación, si los nombres de los archivos tienen espacios, es posible que las comillas deban rodear la subfunción que devuelve el nombre para mover los archivos a:
for f in fgh*; do mv "$f" "$(echo $f | sed ''s/^fgh/jkl/g'')"; done
El cambio de nombre podría no estar en todos los sistemas. así que si no lo tiene, use el shell este ejemplo en bash shell
for f in fgh*; do mv "$f" "${f/fgh/xxx}";done
En Solaris puedes probar:
for file in `find ./ -name "*TextForRename*"`; do
mv -f "$file" "${file/TextForRename/NewText}"
done
Escribí este script para buscar todos los archivos .mkv que cambian de nombre recursivamente los archivos encontrados a .avi. Puedes personalizarlo según tus necesidades. He agregado algunas otras cosas, como obtener el directorio de archivos, la extensión, el nombre de archivo de una ruta de archivo en caso de que necesite consultar algo en el futuro.
find . -type f -name "*.mkv" | while read fp; do
fd=$(dirname "${fp}");
fn=$(basename "${fp}");
ext="${fn##*.}";
f="${fn%.*}";
new_fp="${fd}/${f}.avi"
mv -v "$fp" "$new_fp"
done;
Esto me funcionó usando regexp:
Quería que los archivos fueran renombrados así:
file0001.txt -> 1.txt
ofile0002.txt -> 2.txt
f_i_l_e0003.txt -> 3.txt
usig [az | _] + 0 * ([0-9] +. ) regexp donde ([0-9] +. ) es una subcadena de grupo para usar en el comando rename
ls -1 | awk ''match($0, /[a-z|/_]+0*([0-9]+.*)/, arr) { print arr[0] " " arr[1] }''|xargs -l mv
Produce:
mv file0001.txt 1.txt
mv ofile0002.txt 2.txt
mv f_i_l_e0003.txt 3.txt
Otro ejemplo:
file001abc.txt -> abc1.txt
ofile0002abcd.txt -> abcd2.txt
ls -1 | awk ''match($0, /[a-z|/_]+0*([0-9]+.*)([a-z]+)/, arr) { print arr[0] " " arr[2] arr[1] }''|xargs -l mv
Produce:
mv file001abc.txt abc1.txt
mv ofile0002abcd.txt abcd2.txt
Advertencia, ten cuidado.
Fue mucho más fácil (en mi Mac) hacer esto en Ruby. Aquí hay 2 ejemplos:
# for your fgh example. renames all files from "fgh..." to "jkl..."
files = Dir[''fgh*'']
files.each do |f|
f2 = f.gsub(''fgh'', ''jkl'')
system("mv #{f} #{f2}")
end
# renames all files in directory from "021roman.rb" to "021_roman.rb"
files = Dir[''*rb''].select {|f| f =~ /^[0-9]{3}[a-zA-Z]+/}
files.each do |f|
f1 = f.clone
f2 = f.insert(3, ''_'')
system("mv #{f1} #{f2}")
end
Hay muchas maneras de hacerlo (no todas estas funcionarán en todos los sistemas unixy):
ls | cut -c4- | xargs -I§ mv fgh§ jkl§
El § puede ser reemplazado por cualquier cosa que le parezca conveniente. Puedes hacer esto con
find -exec
también, pero eso se comporta de manera muy diferente en muchos sistemas, por lo que generalmente evito eso.for f in fgh*; do mv "$f" "${f/fgh/jkl}";done
Crudo pero efectivo como dicen
rename ''s/^fgh/jkl/'' fgh*
Muy bonito, pero el cambio de nombre no está presente en BSD, que es el sistema de UNIX más común.
rename fgh jkl fgh*
ls | perl -ne ''chomp; next unless -e; $o = $_; s/fgh/jkl/; next if -e; rename $o, $_'';
Si insistes en usar Perl, pero no hay cambio de nombre en tu sistema, puedes usar este monstruo.
Algunos de ellos son un poco complicados y la lista está lejos de ser completa, pero aquí encontrará lo que desea para prácticamente todos los sistemas UNIX.
Hay varias formas, pero usar rename
probablemente sea la más fácil.
Usando una versión de rename
:
rename ''s/^fgh/jkl/'' fgh*
Usando otra versión de rename
(igual que la respuesta de Judy2K ):
rename fgh jkl fgh*
Debes consultar la página de manual de tu plataforma para ver cuál de las anteriores aplica.
Mi versión de renombrar archivos masivos:
for i in *; do
echo "mv $i $i"
done |
sed -e "s#from_pattern#to_pattern#g” > result1.sh
sh result1.sh
Para instalar el script de rename Perl:
sudo cpan install File::Rename
Hay dos renombramientos como se menciona en los comentarios en la respuesta de Stephan202. Las distribuciones basadas en Debian tienen el rename . Las distros redhat / rpm tienen el rename
OS X no tiene uno instalado de forma predeterminada (al menos en 10.8), ni Windows / Cygwin.
Recomendaría usar mi propio script, que resuelve este problema. También tiene opciones para cambiar la codificación de los nombres de los archivos y convertir los signos diacríticos en caracteres precompuestos, un problema que siempre tengo cuando copio archivos desde mi Mac.
También puede utilizar el siguiente script. Es muy fácil de ejecutar en la terminal ...
// Renombrar múltiples archivos a la vez
for file in FILE_NAME*
do
mv -i "${file}" "${file/FILE_NAME/RENAMED_FILE_NAME}"
done
Ejemplo:-
for file in hello*
do
mv -i "${file}" "${file/hello/JAISHREE}"
done
Un script genérico para ejecutar una expresión sed
en una lista de archivos (combina la solución sed
con la solución para rename
el rename
):
#!/bin/sh
e=$1
shift
for f in $*; do
fNew=$(echo "$f" | sed "$e")
mv "$f" "$fNew";
done
Invoca pasando la secuencia de comandos una expresión sed
y luego cualquier lista de archivos, como una versión de rename
:
script.sh ''s/^fgh/jkl/'' fgh*
Usando StringSolver herramientas de StringSolver (Windows y Linux bash) que se procesan con ejemplos:
filter fghfilea ok fghreport ok notfghfile notok; mv --all --filter fghfilea jklfilea
Primero calcula un filtro basado en ejemplos , donde la entrada son los nombres de archivo y la salida (ok y notok, cadenas arbitrarias). Si el filtro tenía la opción --auto o se invocó solo después de este comando, crearía una carpeta ok
y una carpeta notok
y notok
archivos respectivamente a ellos.
Luego, utilizando el filtro, el comando mv
es un movimiento semiautomático que se vuelve automático con el modificador --auto. Usando el filtro anterior gracias a --filter, encuentra una asignación de fghfilea
a jklfilea
y luego la aplica a todos los archivos filtrados.
Otras soluciones de una línea
Otras formas equivalentes de hacer lo mismo (cada línea es equivalente), para que pueda elegir su forma favorita de hacerlo.
filter fghfilea ok fghreport ok notfghfile notok; mv --filter fghfilea jklfilea; mv
filter fghfilea ok fghreport ok notfghfile notok; auto --all --filter fghfilea "mv fghfilea jklfilea"
# Even better, automatically infers the file name
filter fghfilea ok fghreport ok notfghfile notok; auto --all --filter "mv fghfilea jklfilea"
Solución de varios pasos
Para encontrar con cuidado si los comandos funcionan bien, puede escribir lo siguiente:
filter fghfilea ok
filter fghfileb ok
filter fghfileb notok
y cuando esté seguro de que el filtro es bueno, realice el primer movimiento:
mv fghfilea jklfilea
Si desea realizar una prueba y usar el filtro anterior, escriba:
mv --test --filter
Si la transformación no es lo que deseaba (p. Ej., Incluso con mv --explain
que ve que algo está mal), puede escribir mv --clear
para reiniciar archivos en movimiento, o agregar más ejemplos mv input1 input2
donde input1 y input2 son otros ejemplos.
Cuando tengas confianza, solo escribe
mv --filter
¡y voilá! Todo el cambio de nombre se realiza mediante el filtro.
DESCARGO DE RESPONSABILIDAD: Soy coautor de este trabajo realizado con fines académicos. También podría haber una característica de producción de bash pronto.
Usando find
, xargs
y sed
:
find . -name "fgh*" -type f -print0 | xargs -0 -I {} sh -c ''mv "{}" "$(dirname "{}")/`echo $(basename "{}") | sed ''s/^fgh/jkl/g''`"''
Es más complejo que la solución de @nik, pero permite renombrar archivos de forma recursiva. Por ejemplo, la estructura,
.
├── fghdir
│ ├── fdhfilea
│ └── fghfilea
├── fghfile/ e
├── fghfilea
├── fghfileb
├── fghfilec
└── other
├── fghfile/ e
├── fghfilea
├── fghfileb
└── fghfilec
se transformaría en esto,
.
├── fghdir
│ ├── fdhfilea
│ └── jklfilea
├── jklfile/ e
├── jklfilea
├── jklfileb
├── jklfilec
└── other
├── jklfile/ e
├── jklfilea
├── jklfileb
└── jklfilec
La clave para hacer que funcione con xargs
es invocar el shell desde xargs .
Utilizando mmv :
mmv "fgh*" "jkl#1"
Utilizando renamer :
$ renamer --find /^fgh/ --replace jkl * --dry-run
Elimine el --dry-run
una vez que esté satisfecho, la salida se ve correcta.
#!/bin/sh
#replace all files ended witn .f77 to .f90 in a directory
for filename in *.f77
do
#echo $filename
#b= echo $filename | cut -d. -f1
#echo $b
mv "${filename}" "${filename%.f77}.f90"
done
rename fgh jkl fgh*