Tengo un ReadyNAS Duo v1 (Sparc) antiguo que ejecuta una versión desconocida de Linux.
Tengo una estructura de carpetas con más de 1000 archivos que quiero mover a una estructura de carpetas basada en la primera letra del nombre del archivo (sin distinción entre mayúsculas y minúsculas).
Idealmente, me gustaría que la estructura del archivo se viera así:
myfiles-+
+-A
+ Apple.txt
+ avocado.txt
+-B
+ Banana.txt
+ broccoli.txt
etc. etc.
He tenido un Google pero solo he encontrado herramientas GUI.
¿Se puede hacer esto a través de la línea de comandos o un script?
Respuesta aceptada:
Aquí hay un poco de una sola línea que hará lo que quieras:
$ mkdir -p output/{A..Z}; for i in tstdir/*; do export FILE=$(basename "$i"); LTR=$(echo" ${FILE:0:1}" | tr [a-z] [A-Z]); mv "$i" "output/$LTR/$FILE" ; done
Aquí está el mismo comando en forma expandida para que pueda ver lo que está pasando:
$ mkdir -p output/{A..Z}
$ for i in tstdir/*; do
FILE=$(basename "$i")
LTR=$(echo "${FILE:0:1}" | tr [a-z] [A-Z])
mv "$i" "output/$LTR/$FILE"
done
Detalles
Lo anterior primero asume que el directorio de salida de solo las letras no existe, por lo que lo creará,
$ mkdir -p output/{A..Z}
El for
loop funciona de la siguiente manera, recorriendo todos los archivos en tstdir/*
. Luego determina el basename
de esta ruta y lo almacena en la variable, $FILE
. Cada iteración a través del bucle se almacena en la variable $i
.
FILE=$(basename "$i")
Luego usamos la capacidad de Bashes para devolver el primer carácter de la variable nombrada, $FILE
y luego use tr
para convertir cualquier carácter en minúsculas a mayúsculas.
LTR=$(echo "${FILE:0:1}" | tr [a-z] [A-Z])
Desglosando esto un poco más:
$ echo "${FILE:0:1}"
s
$ echo "${FILE:0:1}"
T
Con el tr
código ahora puede ver lo que está pasando:
$ echo "${FILE:0:1}" | tr [a-z] [A-Z]
S
$ echo "${FILE:0:1}" | tr [a-z] [A-Z]
T
El resto del comando simplemente mueve los archivos a su directorio de primera letra correspondiente.
Ejemplo
Digamos que tenemos este directorio de archivos:
$ touch {a-z}file {A-Z}file
$ tree tstdir/ | head -10
tstdir/
|-- afile
|-- Afile
|-- bfile
|-- Bfile
|-- cfile
|-- Cfile
|-- dfile
|-- Dfile
|-- efile
...
Después de ejecutar el trazador de líneas:
$ tree output/ | head -10
output/
|-- A
| |-- afile
| `-- Afile
|-- B
| |-- bfile
| `-- Bfile
|-- C
| |-- cfile
| `-- Cfile
...