Ho un vecchio ReadyNAS Duo v1 (Sparc) che esegue una versione sconosciuta di Linux.
Ho una struttura di cartelle con oltre 1.000 file che voglio spostare in una struttura di cartelle basata sulla prima lettera del nome del file (senza distinzione tra maiuscole e minuscole).
Idealmente, vorrei che la struttura del file fosse simile a questa:
myfiles-+
+-A
+ Apple.txt
+ avocado.txt
+-B
+ Banana.txt
+ broccoli.txt
etc. etc.
Ho avuto un Google ma ho trovato solo strumenti GUI.
È possibile farlo tramite la riga di comando o uno script?
Risposta accettata:
Ecco un po' di una fodera che farà quello che vuoi:
$ 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
Ecco lo stesso comando in forma estesa in modo da poter vedere cosa sta succedendo:
$ 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
Dettagli
Quanto sopra presuppone prima che la directory di output delle sole lettere non esista e quindi la creerà,
$ mkdir -p output/{A..Z}
Il for
loop funziona come segue, scorrendo tutti i file in tstdir/*
. Quindi determina il basename
di questo percorso e lo memorizza nella variabile $FILE
. Ogni iterazione del ciclo è memorizzata nella variabile $i
.
FILE=$(basename "$i")
Usiamo quindi l'abilità di Bashes per restituire il primo carattere della variabile denominata, $FILE
, quindi usa tr
per convertire i caratteri minuscoli in maiuscoli.
LTR=$(echo "${FILE:0:1}" | tr [a-z] [A-Z])
Scomponendo un po' di più:
$ echo "${FILE:0:1}"
s
$ echo "${FILE:0:1}"
T
Con il tr
codice ora puoi vedere cosa sta succedendo:
$ echo "${FILE:0:1}" | tr [a-z] [A-Z]
S
$ echo "${FILE:0:1}" | tr [a-z] [A-Z]
T
Il resto del comando sposta semplicemente i file nella directory della prima lettera corrispondente.
Esempio
Supponiamo di avere questa directory di file:
$ touch {a-z}file {A-Z}file
$ tree tstdir/ | head -10
tstdir/
|-- afile
|-- Afile
|-- bfile
|-- Bfile
|-- cfile
|-- Cfile
|-- dfile
|-- Dfile
|-- efile
...
Dopo aver eseguito l'unico liner:
$ tree output/ | head -10
output/
|-- A
| |-- afile
| `-- Afile
|-- B
| |-- bfile
| `-- Bfile
|-- C
| |-- cfile
| `-- Cfile
...