
Une corbeille pour la ligne de commande ? C’est possible

Il est une caractéristique particulière qu’il ne faut jamais négliger avec la ligne de commande sous Linux : chaque suppression de fichier est directe, définitive (sauf dans le cas où le fichier est encore ouvert par une application, ce qui permet son sauvetage). Un mécanisme de corbeille, tel que tout le monde le connaît aujourd’hui, permet éventuellement de vérifier avant de choisir de supprimer définitivement un fichier. Et si on mettait ça en place pour notre bon vieux shell ?
Pré-requis, principes, limitations
Évidemment, cet article ne conviendra qu’à ceux manipulant souvent leurs fichiers/dossiers en ligne de commande, et qui voudraient s’ajouter une sécurité avant de faire une (grosse) bourde. Et on va tout faire en Shell, parce que ça suffit pour l’usage et que j’ai pas encore assez de maîtrise en Python pour me sentir de vous le proposer avec ce langage.
On va gérer un format « simple » de corbeille, ce qui veut dire qu’on ne sauvegardera pas l’emplacement d’origine du fichier/dossier passé en argument. On conservera tout de même l’arborescence d’un dossier le cas échéant. Cette corbeille sera donc un dossier, qu’on créera de manière à ce qu’il soit accessible à tous. On ajoutera le timestamp au nom du fichier/dossier pour pallier aux noms dupliqués, ce qui entraînerait l’écrasement du fichier/dossier de destination.
Ensuite, je prend le risque, parce que je suis un fou, de remplacer tout simplement la commande rm au moyen d’un alias (qu’on a déjà vu dans la personnalisation du bash), qui va se comporter au final comme la commande mv, qui va donc déplacer les fichiers en question dans le dossier créé. Conséquence de l’utilisation d’alias, pour effectivement supprimer le fichier, il faudra faire appel « manuellement » à la commande rm par son chemin absolu /usr/bin/rm.
L’alias pointera vers un script nommé tdel (pour trash delete), placé dans /usr/bin, car on va tout de même gérer le cas où l’on indique plusieurs dossiers/fichiers à notre rm transformé.
Création du dossier « trash »
Le chemin utilisé pour la corbeille sera /trash. Mais bien entendu, on aura le choix : soit on crée le dossier directement, et donc sa taille sera limitée par la partition système. Une autre solution est de créer ce dossier ailleurs, sur une partition « généreuse », et de faire un lien symbolique vers le dossier en question.
Sur mon serveur maison, le RAID5 de 3To est « monté » dans le dossier /media/1f3346d1-b4a2-4e02-a259-d296fbfcbed9 (Dieu bénisse l’auto-complétion). Donc je crée le dossier trash à cet endroit, et je fais un lien symbolique :
1 2 3 4 |
cd /media/1f3346d1-b4a2-4e02-a259-d296fbfcbed9 mkdir trash chmod 777 trash ln -s /media/1f3346d1-b4a2-4e02-a259-d296fbfcbed9/trash /trash |
Le chmod n’est là que pour permettre au dossier d’être « rempli » par tous les utilisateurs. J’en parle en conclusion, mais c’est une piste d’améliorations. En effet, ce n’est pas très « sécurisé ».
Création du script
Le script va donc « parcourir » la liste des arguments (les noms des fichiers), et les « supprimer » un par un au moyen d’une boucle « while« .
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 |
#!/bin/bash TRASHPATH="/trash" if [ -z $1 ]; then echo 'del : Fichier ou répertoire non spécifié' exit 1 fi timestamp=`date '+%s'` while [ $# -ge 1 ]; do fichier=`echo $1 | sed 's/\/$//'` if [ ! -e $fichier ]; then echo "$0 : Fichier ou répertoire '$fichier' introuvable" else #echo -n "$0 : Etes-vous sûr de vouloir supprimer '$file' ? [o/N] " #read confirm #if [ -z $confirm ]; then #confirm='n' #fi #if [ $confirm == 'o' || $confirm == 'O' ]; then echo "Suppression du fichier ou répertoire '$file' ..." file_name=`basename $fichier` mv $fichier ${TRASHPATH}/${file_name}-$timestamp #fi fi shift done |
J’ai commenté les lignes permettant de poser la question avant de déplacer les fichiers supprimés. L’avantage ici, c’est que Bash n’en a rien à secouer de l’indentation, contrairement à Python.
Une fois le fichier /usr/bin/tdel créé et rempli, on le sauvegarde, et on n’oublie pas de le rendre exécutable (sinon, comme moi on aura l’impression qu’il ne fonctionne pas…) :
1 |
chmod +x /usr/bin/tdel |
Mise en place de l’alias (ou pas)
Si vous souhaitez disposer de la corbeille pour tous les utilisateurs, le mieux est de définir l’alias dans /etc/bash.bashrc, sinon, le fichier ~/.bashrc (votre fichier de configuration perso) conviendra :
1 |
alias rm='/usr/bin/tdel' |
Les utilisateurs qui n’auront pas configuré l’alias pourront toujours faire appel à tdel manuellement pour déplacer dans la corbeille au lieu de supprimer.
Aller plus loin
Ce script est une base. Vous pouvez si vous le souhaitez implémenter une gestion d’options (par exemple, -f pour éviter la question, plutôt que de commenter les lignes de test), rendre les dialogues plus « GNU-style » (Usage : blablabla [OPTION] fichier, ce genre de choses), voire même carrément le style de codage, parce que j’avoue, c’est un peu fait avec la méthode LA RACHE. On voit aussi qu’il n’y a pratiquement aucune gestion des erreurs. On peut aussi « découper » le dossier trash avec des sous-dossiers par utilisateur.
Bref, ce script n’est ici qu’une sorte de « proof of concept », que vous pouvez utiliser tel quel, en ayant bien conscience des nombreuses limitations dont il est atteint, ou alors vous en servir comme exercice pour implémenter les améliorations qui sont possibles. Vous avez aussi le droit de dire « fuck it, j’ai pas besoin de corbeille » ou me pourrir dans les commentaires avec un « c’est horrible ton code, j’ai les yeux qui saignent ».
Ceux qui voudraient une solution complète s’appuyant sur la corbeille de l’environnement de bureau pourront se tourner vers trash-cli, une suite d’utilitaires écrit en Python. Vos fichiers supprimés apparaîtront alors dans la corbeille lorsqu’on la fouillera avec l’explorateur.
C’est une idée que j’avais envisagé sans jamais prendre le temps de le faire. Par contre pourquoi ne pas utiliser un dossier du style ~/.trash ? ça évite de gérer les droits utilisateurs, suffit de tester son existence à chaque lancement, si on est dans le cas de session à quota d’espace ce sera géré automatiquement pour chaque user, on a un trash complètement indépendant à chaque utilisateur qui peut donc utiliser ou pas cette méthode via l’alias sans être concerné par ce que font les autres.
Eh bien justement pour proposer des modifications dans les commentaires 😛