La Lanterne Rouge

Warning: Geek Inside

Un habile oneliner rsync

- Posted in Sans catégorie by

Sur le PC portable que je prends en vacances, la place est limitée. Il est donc impossible de synchroniser toute la musique dessus. Comment faire ?

Admettons que je ne veuille que les dossiers d'artistes les plus récents tiens, ça serait pas mal, ça me permettrait d'avoir au moins les nouveautés à portée de main d'oreilles.

Comment faire en sorte de calculer dynamiquement cette liste et l'écrire dans un fichier qui pourra ensuite être donné à rsync pour faire la synchro uniquement sur ces dossiers ?

Avec un bon gros one-liner bien sûûûûr.

rsync mon-nas::music/ \
    | awk '$5=="."{next;} {printf("%s%s",$3,OFS); for(i=5;i<=NF;i++) printf("%s%s",$i,i==NF?"\n":OFS)}'\
    | sort \
    | tail -n50 \
    | cut -d' ' -f2- \
    | sort \
    | awk '{print "+ /" $0 "/***"}' \
    >> $rsynclist

Ouais c'est un peu touffu, et la partie awk est pas fofolle mais ça marche.

On détaille :

rsync mon-nas::music/
on liste le contenu du partage music servi via rsyncd par la machine mon-nas (on ne fait que lister ici). La sortie donne quelque chose comme :

drwxrwxr-x              0 2025/09/12 11:54:16 .
drwxrwxr-x              0 2023/02/26 04:14:59 Pink Floyd
drwxrwxr-x              0 2013/12/28 13:55:19 The Alan Parsons Project
drwxrwxr-x              0 2025/08/19 08:47:24 ZZ Top
...

awk '$5=="."{next;} {printf("%s%s",$3,OFS); for(i=5;i<=NF;i++) printf("%s%s",$i,i==NF?"\n":OFS)}'
Ici le but est de récupérer les champs qui nous intéressent (date + nom) afin de trier plus tard par date.
Le champ de la date est le 3ème, donc $3 qu'on concatène au séparateur OFS (espace), puis sans ajouter de retour à la ligne, on va y concaténer tous les champs à partir du 5ème ($5) jusqu'au dernier (NF). Quand on atteint NF, on concatène finalement avec un \n et on affiche le tout, ce qui a pour bon goût de passer à la ligne suivante.
Ah oui le $5=="."{next;} permet simplement d'exclure le dossier courant, qui apparaît lui aussi dans la liste sinon.
Si on observe la sortie ici on a à présent :

2023/02/26 Pink Floyd
2013/12/28 The Alan Parsons Project
2025/08/19 ZZ Top

sort
Là c'est assez simple : comme la date préfixe chaque ligne, on a simplement les trier par ordre alphabétique pour avoir les plus récentes en fin de liste.

2013/12/28 The Alan Parsons Project
2023/02/26 Pink Floyd
2025/08/19 ZZ Top

tail -n50 On ne garde que les 50 dernières lignes (donc 50 plus récentes)

cut -d' ' -f2- Maintenant que la liste est filtrée, on peut virer la date en préfixe pour ne conserver que le nom du dossier sur chaque ligne.
-d' ' = séparateur espace
-f2- = 2ème champ et tous les suivants (oui puisqu'il y a des espaces dans les noms de dossiers)

The Alan Parsons Project
Pink Floyd
ZZ Top

sort On re-trie par ordre alphabétique, mais cette fois sur les noms de dossiers seuls.

Pink Floyd
The Alan Parsons Project
ZZ Top

awk '{print "+ /" $0 "/***"}' On génère une liste de tous les dossiers utilisable ensuite par la directive --include-from de rsync.

+ Pink Floyd/***
+ The Alan Parsons Project/***
+ ZZ Top/***

Et après vous me direz ? Oui j'avoue, le one-liner c'est que pour la préparation du fichier, mais uniquement pour que ça soit pas trop indigeste parce qu'on pourrait aller plus loin.

Le script complet c'est plutôt celui-là :

#!/bin/bash
echo '+ /' > rsync-music.lst
rsync mon-nas::music/ \
    | awk '$5=="."{next;} {printf("%s%s",$3,OFS); for(i=5;i<=NF;i++) printf("%s%s",$i,i==NF?"\n":OFS)}'\
    | sort \
    | tail -n50 \
    | cut -d' ' -f2- \
    | sort \
    | awk '{print "+ /" $0 "/***"}' \
    >> rsync-music.lst
echo '- /**' >> rsync-music.lst

rsync -av --delete-before --include-from=rsync-music.lst mon-nas::music/ ~/Musique/

Il encadre le résultat du gros one-liner détaillé précédemment par 2 directives importantes pour le bon fonctionnement du --include-from :
+ / au début du fichier qui inclut déjà le dossier racine
- /** en fin de fichier qui exclut tous les dossiers qui n'ont pas été préalablement autorisés

Ce qui donne au final un fichier rsync-music.lst avec le contenu suivant :

+ /
+ Pink Floyd/***
+ The Alan Parsons Project/***
+ ZZ Top/***
- /**

Et avec ça, mise à jour de la musique en une commande et en quelques minutes !