La pregunta en sí no es exacta también, porque el OP habla de:
- nombres de archivos como
ABC 123456
(sin extensión), pero en el código de ejemplo que usa la extensión *.txt
-
agrega un guión entre dos bloques (por ejemplo, dónde está el espacio) como
ABC - 123456
, pero en la siguiente toma aproximadamente counting to 4
y count 3
, por ejemplo no está claro qué debe hacer la secuencia de comandos, por ejemplo, si encuentra ABCD 12
o AB 345
- también, desea mantener el espacio al final, lo que es extraño, pero está bien;)
El problema se puede dividir en 3 partes separadas:
- seleccionando los archivos correctos para el cambio de nombre
- preparar el nuevo nombre de archivo, reemplazando / agregando caracteres en el antiguo
- el nombre "físico"
Anuncio "seleccionando los archivos correctos". La selección de los archivos puede realizarse mediante algunas utilidades externas, por ejemplo, mediante el comando find
.
Los principales beneficios de find
son:
- también puede buscar archivos recursivamente en los subdirectorios
- es posible con mayor precisión seleccionar los archivos correctos, por ejemplo, excluir directorios, seleccionar archivos por tiempo o tamaño y así sucesivamente. (verifique desde la terminal
man find
.)
Anuncio "preparar el nuevo nombre". Esto se puede hacer por programas externos,
como sed
o awk
o cualquier programa que pueda manipular texto en shell
Los scripts, o se pueden hacer (en algunos casos simples como este) dentro de
El mismo bash
, y es posible guardar una ejecución de comando costosa.
(Para cientos de miles de archivos hace una diferencia).
Lo siguiente:
${file/ /-}
sustituye (reemplaza) un espacio (la parte / /
) con el guión ( /-
). Así que es posible escribir
mv "$file" "${file/ /-}"
y guarda la ejecución sed
.
Entonces, una de las soluciones alternativas podría ser , por ejemplo, la siguiente:
#!/bin/bash
while IFS= read -r -d $'find . -maxdepth 1 -type f -iname "*.jpg" -print0 |\
perl -0nle '$n=$_; $n=~s/ /-/; rename $_,$n unless($_ eq $n || -e $n)'
' filename
do
newfilename="${filename/ /-}"
[[ "$filename" != "$newfilename" ]] && echo mv -i "$filename" "$newfilename"
done < <(find . -maxdepth 1 -type f -iname "* *.jpg" -print0)
El abobe es para DRY RUN ; solo se mostrará lo que se hará. Para la ejecución real, elimine echo
.
Descomposición:
-
seleccionando los archivos correctos para el cambio de nombre: find . -maxdepth 1 -type f -iname "* *.jpg" -print0
encontrará todos
- lo que está solo en el directorio actual (
-maxdepth 1
)
- y son archivos sin formato (
-type f
)
- y su nombre coincide con (cualquier cosa) (espacio) (cualquier cosa) .jpg mayúsculas insensiblemente, por ejemplo, el nombre debe contener un espacio
- suministre los nombres de archivo como terminados en nulo , por lo que su nombre también puede contener caracteres de nueva línea. (
-print0
)
-
el ciclo while IFS= read -r -d $'find
' filename; do ... done < <( )
- lee la salida del comando
-d $'-r
'
anterior
- donde los nombres de archivo están terminados en nulo (
IFS=
)
- ignorar cualquier carácter escapado (
newfilename="${filename/ /-}"
) / tema avanzado, no es necesario explicarlo aquí /
- el
bash
evita el recorte de los espacios en blanco iniciales y finales del nombre de archivo (también, un tema un poco avanzado)
-
preparando el nuevo nombre de archivo ${filename/ /- }
- se realiza mediante
mv
internamente (sin ejecutar un comando externo).
- si desea conservar el espacio final después del guión, use
man mv
-
el cambio de nombre real se realiza mediante el comando -i
(consulte mv
desde el terminal), donde
-
newfilename
lo que preguntará al usuario si aquí ya hay un archivo con el nuevo nombre de archivo (no lo invalide)
-
y el filename
se ejecuta solo cuando el [[ "$filename" != "$newfilename" ]]
es diferente del mv
mv
La solución anterior es en su mayoría propensa a errores, pero aún no es muy efectiva,
Porque para cientos de miles de archivos se ejecutarán cientos de
mil veces el comando find
.
La solución puede ser: usar algunos
utilidad, lo que puede leer los nombres de archivo y hacer el cambio de nombre sin
ejecutando el comando mv
N-times.
Por ejemplo, la "pistola grande" de los administradores del sistema el "perl", como:
find . -maxdepth 1 -type f -iname "*.jpg" -print0 |\
perl -0nle '$n=$_; $n=~s/ /-/; print qq{old:$_ new:$n\n} unless($_ eq $n || -e $n)' #print instead of the rename
lo que cambiará el nombre de todos los archivos lo que genera el bash
en una ejecución, por ejemplo, mucho más rápido que miles de %code% de ejecuciones.
La prueba Tor (DRY RUN) usa lo siguiente:
${file/ /-}
Sal: el perl es lo suficientemente poderoso como para manejar todo por sí mismo, por ejemplo. El comando de búsqueda también, pero es un tema más avanzado ...
Ps2: mi inglés es mucho peor que mi %code% , por lo que alguien podría editar esta publicación para agregar / corregir cosas ...;)