para - renombrar archivos recursivamente linux
Cómo reemplazar espacios en nombres de archivos usando un script bash (16)
Aquí hay una solución -exec de encontrar (bastante detallada) que escribe "el archivo ya existe" advertencias en stderr:
function trspace() {
declare dir name bname dname newname replace_char
[ $# -lt 1 -o $# -gt 2 ] && { echo "usage: trspace dir char"; return 1; }
dir="${1}"
replace_char="${2:-_}"
find "${dir}" -xdev -depth -name $''*[ /t/r/n/v/f]*'' -exec bash -c ''
for ((i=1; i<=$#; i++)); do
name="${@:i:1}"
dname="${name%/*}"
bname="${name##*/}"
newname="${dname}/${bname//[[:space:]]/${0}}"
if [[ -e "${newname}" ]]; then
echo "Warning: file already exists: ${newname}" 1>&2
else
mv "${name}" "${newname}"
fi
done
'' "${replace_char}" ''{}'' +
}
trspace rootdir _
¿Puede alguien recomendar una solución segura para reemplazar recursivamente los espacios con guiones bajos en los nombres de archivos y directorios a partir de un directorio raíz dado? Por ejemplo:
$ tree
.
|-- a dir
| `-- file with spaces.txt
`-- b dir
|-- another file with spaces.txt
`-- yet another file with spaces.pdf
se convierte en:
$ tree
.
|-- a_dir
| `-- file_with_spaces.txt
`-- b_dir
|-- another_file_with_spaces.txt
`-- yet_another_file_with_spaces.pdf
Aquí hay una solución de script bash de tamaño razonable
#!/bin/bash
(
IFS=$''/n''
for y in $(ls $1)
do
mv $1/`echo $y | sed ''s/ /// /g''` $1/`echo "$y" | sed ''s/ /_/g''`
done
)
Encontré alrededor de este script, puede ser interesante :)
IFS=$''/n'';for f in `find .`; do file=$(echo $f | tr [:blank:] ''_''); [ -e $f ] && [ ! -e $file ] && mv "$f" $file;done;unset IFS
Este hace un poco más. Lo uso para cambiar el nombre de mis torrents descargados (sin caracteres especiales (no ASCII), espacios, puntos múltiples, etc.).
#!/usr/bin/perl
&rena(`find . -type d`);
&rena(`find . -type f`);
sub rena
{
($elems)=@_;
@t=split //n/,$elems;
for $e (@t)
{
$_=$e;
# remove ./ of find
s/^/.////;
# non ascii transliterate
tr [/200-/377][_];
tr [/000-/40][_];
# special characters we do not want in paths
s/[ /-/,/;/?/+/'/"/!/[/]/(/)/@/#]/_/g;
# multiple dots except for extension
while (//..*/./)
{
s//./_/;
}
# only one _ consecutive
s/_+/_/g;
next if ($_ eq $e ) or ("./$_" eq $e);
print "$e -> $_/n";
rename ($e,$_);
}
}
Esto solo encuentra archivos dentro del directorio actual y los renombra . Tengo este alias
find ./ -name "* *" -type f -d 1 | perl -ple ''$file = $_; $file =~ s//s+/_/g; rename($_, $file);
Para aquellos que luchan con esto usando macOS, primero instale todas las herramientas:
brew install tree findutils rename
luego, cuando sea necesario para cambiar el nombre, cree un alias para GNU find (gfind) como find y luego ejecute la línea de @Michel Krelin :,
alias find=gfind
find . -depth -name ''* *'' /
| while IFS= read -r f ; do mv -i "$f" "$(dirname "$f")/$(basename "$f"|tr '' '' _)" ; done
Para archivos en la carpeta llamada / archivos
for i in `IFS="";find /files -name */ *`
do
echo $i
done > /tmp/list
while read line
do
mv "$line" `echo $line | sed ''s/ /_/g''`
done < /tmp/list
rm /tmp/list
Solo hago uno para mi propio propósito. Puedes usarlo como referencia.
#!/bin/bash
cd /vzwhome/c0cheh1/dev_source/UB_14_8
for file in *
do
echo $file
cd "/vzwhome/c0cheh1/dev_source/UB_14_8/$file/Configuration/$file"
echo "==> `pwd`"
for subfile in */ *; do [ -d "$subfile" ] && ( mv "$subfile" "$(echo $subfile | sed -e ''s/ /_/g'')" ); done
ls
cd /vzwhome/c0cheh1/dev_source/UB_14_8
done
Una solución para encontrar / renombrar . renombrar es parte de util-linux.
Primero debe descender la profundidad, porque un nombre de archivo de espacio en blanco puede ser parte de un directorio de espacio en blanco:
find /tmp/ -depth -name "* *" -execdir rename " " "_" "{}" ";"
Use rename
(también prename
como prename
) que es un script de Perl que puede estar en su sistema ya. Hazlo en dos pasos:
find -name "* *" -type d | rename ''s/ /_/g'' # do the directories first
find -name "* *" -type f | rename ''s/ /_/g''
Basado en la respuesta de Jürgen y capaz de manejar múltiples capas de archivos y directorios en un solo enlace usando la versión "Revisión 1.5 1998/12/18 16:16:31 rmb1" de /usr/bin/rename
(una secuencia de comandos de Perl):
find /tmp/ -depth -name "* *" -execdir rename ''s/ /_/g'' "{}" /;
Versión recursiva de las respuestas de Naidim.
find . -name "* *" | awk ''{ print length, $0 }'' | sort -nr -s | cut -d" " -f2- | while read f; do base=$(basename "$f"); newbase="${base// /_}"; mv "$(dirname "$f")/$(basename "$f")" "$(dirname "$f")/$newbase"; done
Yo suelo:
for f in */ *; do mv "$f" "${f// /_}"; done
Aunque no es recursivo, es bastante rápido y simple. Estoy seguro de que alguien aquí podría actualizarlo para ser recursivo.
La parte "$ {f // / _}" utiliza el mecanismo de expansión de parámetros de bash para reemplazar un patrón dentro de un parámetro con la cadena suministrada. La sintaxis relevante es "$ {parámetro / patrón / cadena}". Consulte: https://www.gnu.org/software/bash/manual/html_node/Shell-Parameter-Expansion.html o http://wiki.bash-hackers.org/syntax/pe .
bash 4.0
#!/bin/bash
shopt -s globstar
for file in **/*/ *
do
mv "$file" "${file// /_}"
done
puedes usar detox
por Doug Harple
detox -r <folder>
puedes usar esto:
find . -name ''* *'' | while read fname
do
new_fname=`echo $fname | tr " " "_"`
if [ -e $new_fname ]
then
echo "File $new_fname already exists. Not replacing $fname"
else
echo "Creating new file $new_fname to replace $fname"
mv "$fname" $new_fname
fi
done
find . -depth -name ''* *'' /
| while IFS= read -r f ; do mv -i "$f" "$(dirname "$f")/$(basename "$f"|tr '' '' _)" ; done
Al principio no lo conseguí, porque no pensé en los directorios.