La pregunta en sí misma no es exacto, porque el OP habla de:
- nombres de archivos como
ABC 123456
(sin extensión), pero en el código de ejemplo utilizando *.txt
de extensión
-
añadir un guión entre dos bloques (por ejemplo, dónde está el espacio) como
ABC - 123456
, pero en la siguiente toma sobre counting to 4
y count 3
, por ejemplo, no exacltly claro cuál es la secuencia de comandos debe hacer, por ejemplo, en caso de encontrar ABCD 12
o AB 345
- también, quieren mantener el espacio final, lo que es extraño - pero OK ;)
El problema es divisible para 3 partes separadas:
- el derecho de seleccionar los archivos para cambiar el nombre de la
- preparando el nuevo nombre de archivo, reemplazar o agregar caracteres en el antiguo
- la "física" cambiar el nombre de
Anuncio de "el derecho de seleccionar los archivos". La selección de los archivos, se puede hacer por algunas utilidades externos, por ejemplo, el find
comando.
Los principales beneficios de la find
son:
- puede buscar archivos de forma recursiva en el sub directorios demasiado
- es posible, más precisamente, de la correcta selección de los archivos, por ejemplo, excluir directorios, seleccione los archivos por tiempo o tamaño y así sucesivamente. (verificación de la terminal
man find
.)
Anuncio de "preparar el nuevo nombre". Esto se puede hacer mediante programas externos,
como sed
o awk
o en cualquier programa que lo puede manipular el texto en shell
secuencias de comandos, o se puede hacer (en algunos casos sencillos como éste) dentro de
el bash
- y es posible guardar una cara de ejecución de comandos.
(para hunderts de miles de archivos se hace una diferencia).
El siguiente:
${file/ /-}
los sustitutos (sustituye a) un espacio (la / /
parte) con el guión (/-
). Así que es posible escribir
mv "$file" "${file/ /-}"
y guardar la sed
de ejecución.
Así que una de las alternativas de solución podría ser, por ejemplo, las siguientes:
#!/bin/bash
while IFS= read -r -d $'\0' filename
do
newfilename="${filename/ /-}"
[[ "$filename" != "$newfilename" ]] && echo mv -i "$filename" "$newfilename"
done < <(find . -maxdepth 1 -type f -iname "* *.jpg" -print0)
El abobe es para el funcionamiento en SECO, ya que sólo se va a mostrar, lo que será hecho, para la real ejecución de quitar el echo
.
Descomposición:
-
el derecho de seleccionar los archivos para cambiar el nombre de: la find . -maxdepth 1 -type f -iname "* *.jpg" -print0
encontrará todos los
- lo son sólo en el directorio actual (
-maxdepth 1
)
- y están los archivos sin (
-type f
)
- y su nombre coincide con el de (algo)(espacio)(nada).jpg caso minúsculas - por ejemplo, el nombre contiene un espacio
- el suministro de los nombres de archivo como terminada en nulo, por lo que su nombre puede contener caracteres de nueva línea. (
-print0
)
-
el ciclo de while IFS= read -r -d $'\0' filename; do ... done < <( )
- lee el resultado de la anterior
find
comando
- donde los nombres de los archivos son terminada en null (
-d $'\0'
)
- ignorar cualquier tipo de caracteres de escape (
-r
) /tema avanzado - no es necesario que se explican aquí/
- el
IFS=
evita el recorte de los iniciales y finales en los espacios en blanco del nombre del archivo (también, un poco de tema avanzado)
-
preparando el nuevo nombre de archivo newfilename="${filename/ /-}"
- se realiza por
bash
internamente (sin ejecutar un comando externo).
- si desea conservar el espacio final después de que el guión uso
${filename/ /- }
-
el actual cambio de nombre se realiza por la mv
comando (ver man mv
desde el terminal), donde
- el
-i
de lo que le pregunta al usuario si aquí ya un archivo con el nuevo nombre de archivo (no reemplazar)
y el mv
sólo se ejecuta cuando el newfilename
es diferente de la filename
[[ "$filename" != "$newfilename" ]]
La solución anterior es principalmente propenso a errores, pero aún así no es muy eficaz,
porque para cientos de miles de archivos de ejecutar cientos de
mil veces el mv
comando.
La solución puede ser: el uso de algunos
utilidad, lo que puede leer los nombres de los archivos y hacer el cambio de nombre sin
la ejecución de la mv
comando N-veces.
Por ejemplo, el "big gun", de los administradores de sistemas el "perl", como:
find . -maxdepth 1 -type f -iname "*.jpg" -print0 |\
perl -0nle '$n=$_; $n=~s/ /-/; rename $_,$n unless($_ eq $n || -e $n)'
lo que va a cambiar el nombre de todos los archivos de lo que las salidas de la find
en la ejecución - por ejemplo, mucho más rápido, ya que miles de mv
de ejecución.
Tor de la prueba (DRY RUN) utilice el siguiente:
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
Ps: el perl es lo suficientemente potente como para manejar todo por sí misma, por ejemplo. el comando buscar demasiado, pero es más avanzadas tema...
Ps2: mi nivel de inglés es mucho peor, ya que mi bash
, por lo que alguien podría amablemente editar este post para añadir/corregir las cosas.. ;)