J'ai un ancien ReadyNAS Duo v1 (Sparc) exécutant une version inconnue de Linux.
J'ai une structure de dossiers avec plus de 1 000 fichiers que je souhaite déplacer dans une structure de dossiers basée sur la première lettre du nom de fichier (insensible à la casse).
Idéalement, j'aimerais que la structure du fichier ressemble à ceci :
myfiles-+
+-A
+ Apple.txt
+ avocado.txt
+-B
+ Banana.txt
+ broccoli.txt
etc. etc.
J'ai eu un Google mais je n'ai trouvé que des outils graphiques.
Cela peut-il être fait via la ligne de commande ou un script ?
Réponse acceptée :
Voici un peu d'un one-liner qui fera ce que vous voulez :
$ 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
Voici la même commande sous forme développée afin que vous puissiez voir ce qui se passe :
$ 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
Détails
Ce qui précède suppose d'abord que le répertoire de sortie des seules lettres n'existe pas et le créera donc,
$ mkdir -p output/{A..Z}
Le for
loop fonctionne comme suit, parcourant tous les fichiers dans tstdir/*
. Il détermine ensuite le basename
de ce chemin et le stocke dans la variable $FILE
. Chaque itération de la boucle est stockée dans la variable $i
.
FILE=$(basename "$i")
Nous utilisons ensuite la capacité de Bashes pour renvoyer le 1er caractère de la variable nommée, $FILE
, puis utilisez tr
pour convertir tous les caractères minuscules en majuscules.
LTR=$(echo "${FILE:0:1}" | tr [a-z] [A-Z])
Décomposer un peu plus :
$ echo "${FILE:0:1}"
s
$ echo "${FILE:0:1}"
T
Avec le tr
code, vous pouvez maintenant voir ce qui se passe :
$ echo "${FILE:0:1}" | tr [a-z] [A-Z]
S
$ echo "${FILE:0:1}" | tr [a-z] [A-Z]
T
Le reste de la commande déplace simplement les fichiers dans leur répertoire de première lettre correspondant.
Exemple
Supposons que nous ayons ce répertoire de fichiers :
$ touch {a-z}file {A-Z}file
$ tree tstdir/ | head -10
tstdir/
|-- afile
|-- Afile
|-- bfile
|-- Bfile
|-- cfile
|-- Cfile
|-- dfile
|-- Dfile
|-- efile
...
Après avoir exécuté la ligne unique :
$ tree output/ | head -10
output/
|-- A
| |-- afile
| `-- Afile
|-- B
| |-- bfile
| `-- Bfile
|-- C
| |-- cfile
| `-- Cfile
...