Voici la donne:
J’ai une carte SD sur laquelle j’ai essayé de copier une sélection de dossiers musicaux. Casse-tête des systèmes de fichier et des compatibilités des cartes SD 64GB aidant, une grande partie des fichiers n’a pas été copié correctement. J’ai donc souhaité faire un RSYNC uniquement des dossiers existants sur la cible afin de pouvoir refaire plusieurs fois la synchro en cas de problème sans avoir à refaire ma sélection de dossiers à chaque fois. Voici à quoi je suis arrivé:
find ./* -maxdepth 0 -type d -print | cut -b 3- | while read line; do rsync -rtzu --progress "/home/mint/music/library/$line/" "/media/mint/C07E-08DE/$line";sleep 5;done
Comme vous pourrez le voir, je suis utilisateur mint. Je suis en effet sur une live Mint pour l’instant, car Windows me posait trop de problème pour cette copie.
J’ai donc:
- /home/mint/music qui est un share de librairie musicale de mon NAS fait maison, monté dans ce dossier.
- /media/mint/C07E-08DE qui est le point de montage de ma carte SD 64GB formatée en vFAT
L’objectif est donc de récupérer la liste des dossiers existants sur la carte SD, et de faire un RSYNC de ces dossiers, en ne recopiant pas les fichiers qui auraient été copiés avec succès au préalable, pour gagner ainsi du temps. La ligne est exécutée depuis /media/mint/C07E-08DE afin d’éviter de s’embêter à devoir supprimer les sous-dossiers de la liste. En effet, si on faisait la commande depuis le root, find nous retournerait l’ensemble du chemin. Or ici, ça ne nous arrange pas. En décortiquant la ligne nous avons donc:
find ./* -type d -maxdepth 0 -print
Cette commande va retourner la liste des dossiers contenus sur la carte SD sous la forme
./ドビュッシー
./2 Many DJ's
./Aaliyah
./Aaron Jerome
./Adam F
./Adiemus
./A Filetta
./Air
./Alanis Morissette
./Alicia Keys
./Alif Tree
./All Saints
- “-type d” retourne uniquement les dossiers
- “-maxdepth 0” ne présente que le premier dossier trouver et pas les sous dossiers
- “-print” permet de retourner le résultat à l’écran
Les deux premiers caractères nous posent problèmes. J’utilise donc la commande cut pour les supprimer. Le paramètre “-b 3-” qui implique que l’on ne retourne que le texte dès le 3ème caractère, jusqu’à la fin de la chaîne. Résultat:
find ./* -maxdepth 0 -type d -print | cut -b 3-
ドビュッシー
2 Many DJ's
Aaliyah
Aaron Jerome
Adam F
Adiemus
A Filetta
Air
Alanis Morissette
Alicia Keys
Alif Tree
All Saints
Amon Tobin
AMOS Tori
Amy Winehouse
Nous avons donc maintenant une liste de variables que nous allons pouvoir utiliser avec RSYNC. Comme chaque variable est sur une ligne, une boucle for n’est pas adéquate. En effet, par défaut “for” va lire au km, et considérer chaque espace comme un séparateur. Or nous avons ici nombre de dossiers contenant des espaces. C’est pourquoi j’utilise la commande read à la place. Et comme il y a des espaces, je dois mettre le chemin entre guillemets, sans quoi il s’arrêtera au premier espace:
find ./* -maxdepth 0 -type d -print | cut -b 3- | while read line; do rsync -rtzu --progress "/home/mint/music/library/$line/" "/media/mint/C07E-08DE/$line";done
Les paramètres de la commande rsync sont:
- -r : recursive: afin de copier chaque sous-dossiers (des albums en occurrence) de chaque dossier de base (les artistes)
- -u : update : Ne copie pas les fichiers qui existent déjà, afin de gagner du temps sur la synchronisation
- -t : times : Préserve les dates et heures de chaque fichier
- -z : Compress : Permet de gagner du temps durant la copie en utilisant les perfs des procs pour compresser les fichiers durant leur transfert.
Nous avons donc maintenant une ligne complète qui exécute les opérations suivantes:
- Retourne la liste des dossiers
- Supprime les deux premiers caractères de chaque ligne
- Exécute une boucle dans laquelle, lit chaque ligne, et pour chaque ligne, exécute rsync -rtzu
J’ai donc maintenant une commande en une ligne pour synchroniser uniquement les dossiers qui existaient déjà sur ma carte SD cible.