Copie batch sous Nautilus

Task spooler

J’ai toujours bien aimé le batch, ça doit doit venir de mes débuts sous IBM MVS/TSO/JCL dans les années 80. J’aime bien l’idée de soumettre les traitements, de les laisser s’exécuter tranquillement, quelque soit leur durée, puis de revenir voir le résultat un peu plus tard.

J’ai découvert assez récemment un outil tout à fait adapté à ce que je cherchais et très simple d’utilisation : task spooler. Le programme gère une file d’attente des jobs (job queue) et, par défaut, un seul s’exécute à la fois.

Sous Debian, le package existe et s’installe simplement:

sudo apt install task-spooler

Pour soumettre un job, il suffit de préfixer la commande par ts (commande prévue par l’auteur de task spooler) ou tsp (sous Debian).

Exemple:

tsp rsync mon_fichier1 host:
tsp rsync mon_fichier2 host:

On a soumis 2 jobs de transfert de fichier qui vont s’exécuter l’un derrière l’autre.

On peut voir l’état des différents jobs avec la commande tsp seule:

% tsp

ID   State      Output               E-Level  Times(r/u/s)   Command [run=0/1]
0    finished   /tmp/ts-out.q7UVkz   -1       0.14/0.04/0.00 rsync mon_fichier1 host:
1    finished   /tmp/ts-out.JcwIkK   -1       0.17/0.04/0.00 rsync mon_fichier2 host:

Les fichiers Output permettent d’avoir la sortie de la commande tandis que la colonne E-level donne le code retour. Ici, on voit que le code -1 indique une erreur, ce qui est normal puisque ni les fichiers existent, ni le host.

Script Nautilus

Et si on utilisait task spooler pour séquencer les copies vers un périphérique lent (réseau, clé USB…) sous Nautilus ? Il suffit d’écrire un script.

Sous Debian/Ubuntu, il faut commencer par l’installation du package nautilus-script-manager.

Ensuite on peut écrire le script dans le répertoire ~/.local/share/nautilus/scripts.

Je vais tout de suite donner le contenu du script et expliquer ensuite le contenu:

#!/bin/zsh
d=$(zenity --file-selection --directory)

if [ $? -eq 0 ] ; then
    for f in ${(@f)NAUTILUS_SCRIPT_SELECTED_FILE_PATHS} ; do
        tsp cp "$f" "$d"
    done
fi

Attention, ce script ne fonctionne que sous zsh.

Comme souvent avec les scripts shell, le diable se cache dans les détails. Ici, c’est dans le (@f) devant la variable NAUTILUS_SCRIPT_SELECTED_FILE_PATHS que réside toute la subtilité.

Revenons au début.

Grâce à la commande zenity, que j’ai découvert à cette occasion, on a une belle fenètre pour cliquer sur le répertoire de destination.

Ensuite, Nautilus passe les fichiers sélectionnés dans la variable NAUTILUS_SCRIPT_SELECTED_FILE_PATHS en séparant chaque nom de fichier par un caractère \n. Et comme les noms de fichiers peuvent contenir des espaces ou tout autre caractère exotique, il faut traiter correctement cette chaine.

Il y a peut-être d’autre solution mais, étant par ailleurs un habitué de Python, j’aime bien les listes qui résolvent élégamment la question des arguments et des délimiteurs. Or zsh possède cette notion via les arrays. Il serait intéressant de pouvoir dire qu’on veut transformer une chaîne séparée par des \n par un array en splitant. Miracle (un fois qu’on a trouvé l’info) : c’est exactement ce que fait (@f). Une fois qu’on a un array propre, il suffit de le parcourir et le reste ne pose pas de difficulté particulière.