Faire 'rm` aller à la corbeille

54

Existe-t-il un script / application Linux qui, au lieu de supprimer des fichiers, les déplace vers un emplacement spécial pour la «corbeille»? Je voudrais cela comme un remplacement pour rm(peut-être même aliasing le dernier; il y a des avantages et des inconvénients pour cela).

Par «corbeille», je veux dire un dossier spécial. Un mv $* ~/.trashfichier unique est une première étape, mais dans l’idéal, il doit également gérer la suppression de plusieurs fichiers du même nom sans écraser les fichiers supprimés plus anciens, et permettre de restaurer les fichiers à leur emplacement d’origine à l’aide d’une simple commande (sorte d’annulation). De plus, il serait bien que la corbeille soit automatiquement vidée au redémarrage (ou un mécanisme similaire pour empêcher une croissance sans fin).

Des solutions partielles existent, mais l’action de «restauration» en particulier n’est pas anodine. Existe-t-il des solutions existantes qui ne reposent pas sur un système de corbeille à partir d'un shell graphique?

(En passant, il y a eu d'innombrables discussions sur la justification de cette approche, plutôt que sur l'utilisation de sauvegardes fréquentes et de VCS. Bien que ces discussions aient un sens, je pense qu'il reste encore un créneau pour ma demande.)

Konrad Rudolph
la source
4
Cela peut être lié à la question du superutilisateur Deux commandes pour déplacer les fichiers dans la corbeille. Quelle est la différence? . Je l'ai utilisé gvfs-trashdans le passé, mais je n'ai jamais eu besoin de restaurer depuis la ligne de commande jusqu'à susciter ma curiosité. La réponse à la question liée peut être utile.
ephsmith
1
@ephsmith Merci, bon lien. Le problème avec ces approches, cependant, est qu’elles sont liées à des implémentations spécifiques de l’environnement de bureau (shell) (quelque chose que je veux éviter).
Konrad Rudolph
1
Est-ce que le déplacement de fichiers d'un système de fichiers vers votre ~ intentionnel? Parce qu'un jour, vous supprimerez peut-être une image iso de 4 Go résidant sur un répertoire monté avec sshfs à partir d'un serveur vraiment distant.
Mischa Arefiev
1
@Mischa Pour être honnête, je n'y ai pas beaucoup réfléchi. Cela dit, il devrait fonctionner avec les droits habituels de l'utilisateur. La cible doit donc être un emplacement accessible en écriture et ne pas nécessiter une configuration excessive.
Konrad Rudolph
3
Faites ce que vous voulez comme les solutions présentées dans les réponses ci-dessous, mais ne le nommez pas . Comme d'autres l'ont fait remarquer, renommer / réaffecter des commandes standard vous rend vulnérable lorsque vous essayez habituellement de les utiliser sur d'autres systèmes, mais cela posera également des problèmes à quiconque (vous aidant peut-être) utilisant votre système / votre compte lorsque des résultats inattendus se produisent.
Joe

Réponses:

37

Il existe une spécification (brouillon) pour la corbeille sur freedesktop.org. C'est apparemment ce qui est généralement mis en œuvre par les environnements de bureau.

Une implémentation en ligne de commande serait trash-cli . Sans avoir examiné de plus près, il semble fournir la fonctionnalité que vous souhaitez. Sinon, dites-nous dans quelle mesure il ne s'agit que d'une solution partielle.

En ce qui concerne l'utilisation de tout programme en remplacement / alias rm, il y a de bonnes raisons de ne pas le faire. Les plus importants pour moi sont:

  • Le programme devrait comprendre / gérer toutes rmles options de et agir en conséquence
  • Cela risquerait de s’habituer à la sémantique de votre "nouvelle entreprise" et d’exécuter des commandes aux conséquences fatales lorsque vous travaillez sur les systèmes d’autres personnes.
zpea
la source
Il y a aussi libtrash qui déplace automatiquement tous les fichiers supprimés dans la corbeille via LD_PRELOAD (mais il semble y avoir plusieurs bogues). Autotrash facilite le nettoyage de la corbeille.
Jofel
Je me pose des questions sur le fait de prendre l'habitude de se servir de la chose. Je suis déjà dans l'habitude, malheureusement.
Konrad Rudolph
@ jofel: libtrash a un très bon concept. Quelques couches plus profondes que les autres approches. Dommage que ce soit buggy (et ne semble pas très actif).
Zpea
4
@ KonradRudolph: Je voulais dire que l'on s'habitue au fait que rm (celui qui a été remplacé) ne supprime pas vraiment quoi que ce soit, de sorte qu'on est moins prudent, car une restauration est toujours possible. Bien sûr, utiliser rm n’est pas une mauvaise chose, ni s’y habituer.
Zpea
4
J'ai fini par utiliser cette solution et à le désactiver rmafin que je ne puisse pas l'utiliser accidentellement (il y a toujours un /bin/rmcas où j'en aurais vraiment besoin).
Konrad Rudolph
9

Trash-cli est une application Linux pouvant être installée à l’aide d’apt-get sous Ubuntu ou de yum dans Fedora. L'utilisation de la commande trash listOfFilesdéplacera le spécifié dans votre corbeille.

namu
la source
À l'appui de cette suggestion: apple.stackexchange.com/a/17637/37190
Ioannis Filippidis
7

Les réponses précédentes mentionnent des commandes trash-cliet rmtrash. Ni ceux-ci ne sont trouvés par défaut sur Ubuntu 18.04, mais la commande gioest. gio help trashSorties commandantes :

Usage:
  gio trash [OPTION…] [LOCATION...]

Move files or directories to the trash.

Options:
  -f, --force     Ignore nonexistent files, never prompt
  --empty         Empty the trash

J'ai testé à l'aide gio trash FILENAMEde la ligne de commande, et cela fonctionne exactement comme si j'avais sélectionné le fichier dans le navigateur de fichiers et cliqué sur le bouton SUPPR: le fichier est déplacé dans le dossier Corbeille du bureau. (La commande ne demande pas de confirmation même si je n'ai pas utilisé l' -foption.)

Suppression de fichiers de cette façon est réversible, tout en étant plus pratique que la redéfinition rmd'être rm -ipour la sécurité et d' avoir à confirmer chaque suppression, ce qui vous laisse toujours pas de chance si vous confirmez accidentellement une suppression , vous ne devriez pas avoir.

J'ai ajouté alias tt='gio trash'à mon fichier de définitions d'alias; ttest un mnémonique pour To Trash.

Ajouté lors de la modification du 2018-06-27: Sur les ordinateurs serveurs, il n’existe pas d’équivalent d’un répertoire de corbeille. J'ai écrit le script Bash suivant qui fait le travail; sur les ordinateurs de bureau, il utilise gio trash, et sur d’autres, le (s) fichier (s) donné (s) en tant que paramètre (s) dans un répertoire de corbeille qu’il crée. Script mis à jour le 2019-09-05.

#!/bin/bash
#
# move-to-trash
#
# Teemu Leisti 2019-09-05
#
# This script moves the files given as arguments to the trash directory, if they
# are not already there. It works both on (Gnome) desktop and server hosts.
#
# The script is intended as a command-line equivalent of deleting a file from a
# graphical file manager, which, in the usual case, moves the deleted file(s) to
# a built-in trash directory. On server hosts, the analogy is not perfect, as
# the script does not offer the functionality of restoring a trashed file to its
# original location, nor that of emptying the trash directory; rather, it offers
# an alternative to the 'rm' command, giving the user the peace of mind that
# they can still undo an unintended deletion before emptying the trash
# directory.
#
# To determine whether it's running on a desktop host, the script tests for the
# existence of the gio utility and of directory ~/.local/share/Trash. In case
# both exist, the script relies on the 'gio trash' command. Otherwise, it treats
# the host as a server.
#
# There is no built-in trash directory on server hosts, so the first invocation
# of the script creates directory ~/.Trash/, unless it already exists.
#
# The script appends a millisecond-resolution time stamp to all the files it
# moves to the trash directory, both to inform the user of the time of the
# deletion, and to avoid overwrites when moving a file to trash.
#
# The script will not choke on a nonexistent file. It outputs the final
# disposition of each argument: does not exist, was already in trash, or was
# moved to trash.


gio_command_exists=0
command -v gio > /dev/null 2>&1
if (( $? == 0 )) ; then
    gio_command_exists=1
fi

# Exit on using an uninitialized variable, and on a command returning an error.
# (The latter setting necessitates appending " || true" to those arithmetic
# calculations and other commands that can return 0, lest the shell interpret
# the result as signalling an error.)
set -eu

is_desktop=0

if [[ -d ~/.local/share/Trash ]] && (( gio_command_exists == 1 )) ; then
    is_desktop=1
    trash_dir_abspath=$(realpath ~/.local/share/Trash)
else
    trash_dir_abspath=$(realpath ~/.Trash)
    if [[ -e $trash_dir_abspath ]] ; then
        if [[ ! -d $trash_dir_abspath ]] ; then
            echo "The file $trash_dir_abspath exists, but is not a directory. Exiting."
            exit 1
        fi
    else
        mkdir $trash_dir_abspath
        echo "Created directory $trash_dir_abspath"
    fi
fi

for file in "$@" ; do
    file_abspath=$(realpath -- "$file")
    file_basename=$(basename -- "$file_abspath")
    if [[ ! -e $file_abspath ]] ; then
        echo "does not exist:   $file_abspath"
    elif [[ "$file_abspath" == "$trash_dir_abspath"* ]] ; then
        echo "already in trash: $file_abspath"
    else
        if (( is_desktop == 1 )) ; then
            gio trash "$file_abspath" || true
        else
            # The name of the moved file shall be the original name plus a
            # millisecond-resolution timestamp.
            move_to_abspath="$trash_dir_abspath/$file_basename-$(date '+%Y-%m-%d-at-%H-%M-%S.%3N')"
            while [[ -e "$move_to_abspath" ]] ; do
                # Generate a new name with a new timestamp, as the previously
                # generated one denoted an existing file.
                move_to_abspath="$trash_dir_abspath/$file_basename-$(date '+%Y-%m-%d-at-%H-%M-%S.%3N')"
            done
            # We're now almost certain that the file denoted by name
            # $move_to_abspath does not exist, as for that to be the case, an
            # extremely unlikely run condition would have had to take place:
            # some other process would have had to create a file with the name
            # $move_to_abspath after the execution of the existence test above.
            # However, to make absolute sure that moving the file to the trash
            # directory will always be successful, we shall give the '-f'
            # (force) flag to the 'mv' command.
            /bin/mv -f "$file_abspath" "$move_to_abspath"
        fi
        echo "moved to trash:   $file_abspath"
    fi
done
Teemu Leisti
la source
5

Il y a un petit utilitaire appelé rmtrash qui fait cela.

Il ne semble pas répondre aux paramètres tels que -rou -f(il semble qu’il s'agisse essentiellement de déplacer le fichier / répertoire dans le répertoire ~ / .Trash), mais il ne remplacera pas les fichiers portant le même nom (il ajoute "Copier" à fichiers / répertoires du même nom).

Installer avec brasser

brew install rmtrash
alias rm='rmtrash' >> ~/.bashrc
FreePender
la source
github.com/nateshmbhat/rm-trash . "rm-trash", gère également les noms de fichiers en double et les suppressions récursives. Vérifiez-le.
Natesh bhat
4

Voici un système de corbeille rapide et sale qui gère les conflits de noms et permet même plusieurs fichiers supprimés sur le même chemin tant que vous ne supprimez pas plus d'un fichier par seconde.

Attention: j'ai tapé ce code directement dans mon navigateur. C'est probablement cassé. Ne l'utilisez pas sur les données de production.

trash_root=~/.trash
mkdir "$trash_root"
newline='
'
trash () (
  time=$(date +%Y%m%d%H%M%S)
  for path; do
    case $path in /*) :;; *) path=$PWD/$path;; esac
    mkdir "$trash_root${path%/*}"
    case ${path##*/} in
      ?*.*) ext="${path##*.}"; ext="${ext##*$newline}";;
      *) ext="";;
    esac
    metadata="Data: $hash.$ext
Date: $time
Path: $path
"
    hash=$(printf %s "$metadata" | sha1sum)
    printf %s "$metadata" "$trash_root/$hash-$time-metadata"
    mv "$path" "$trash_root/$hash.$ext"
  done
)

untrash () (
  IFS='
  '
  root=$PWD
  cd "$trash_root" || return 2
  err=0
  for path; do
    if [ -e "$path" ]; then
      echo 1>&2 "Not even attempting to untrash $path over an existing file"
      if [ $err -gt 2 ]; then err=2; fi
      continue
    fi
    case $path in /*) :;; *) path=$root/$path;; esac 
    if metadata=$(grep -l -F -x "Path: $path" *-metadata |
                  sort -t - -k 2 | tail -n 1); then
      mv "${metadata%%-*}".* "$path"
    else
      echo 1>&2 "$path: no such deleted file"
      if [ $err -gt 1 ]; then err=1; fi
    fi
  done
  return $err
)

Problèmes connus:

  • Ne vous en sortez pas si vous essayez de supprimer le même fichier plusieurs fois simultanément.
  • Le répertoire de la corbeille peut devenir énorme, les fichiers doivent être répartis dans des sous-répertoires basés sur les premiers chiffres du hachage.
  • trashdevrait faire face aux nouvelles lignes dans les noms de fichiers, mais untrashne le fait pas, car elle repose sur grepet les nouvelles lignes ne sont pas échappées dans le fichier de métadonnées.
Gilles, arrête de faire le mal
la source
2

Commencez par définir une move_to_trashfonction:

move_to_trash () {
    mv "$@" ~/.trash
}

Puis alias rmà cela:

alias rm='move_to_trash'

Vous pouvez toujours appeler vieux rmen échappant avec une barre oblique inverse, comme ceci: \rm.

Je ne sais pas comment vider le répertoire de la corbeille au redémarrage (en fonction du système, vous devrez peut-être consulter les rc*scripts), mais il peut également être intéressant de créer une crontâche qui vide le répertoire périodiquement.

Rahmu
la source
2
Malheureusement, c'était la partie facile…: /
Konrad Rudolph
Ce script peut également créer un fichier texte dans un répertoire caché pour chaque fichier contenant le répertoire dans lequel il se trouvait. Un script de restauration peut lire l'ancien emplacement et le déplacer à nouveau.
ephsmith
Cela risquerait également de provoquer la collision de plusieurs fichiers supprimés portant le même nom dans le répertoire Corbeille, et seul le dernier "supprimé" survivrait pour pouvoir être récupéré.
Killermist
@ Killermist, oui. Bien sûr, il faudrait faire quelque chose de plus avec la commande move. Nommez le fichier "mis à la corbeille" comme vous le souhaitez et conservez le chemin d'origine: | Tout cela crie "pourquoi recréer la roue". Il existe des solutions à ce problème.
ephsmith
En outre, utilisez un nom d'alias différent. Travaillez sur une autre machine sans vos alias, un appel rmet vos fichiers. delpourrait être un meilleur choix.
Glenn Jackman
1

Vous pouvez utiliser mon del:

http://fex.belwue.de/fstools/del.html

del déplace les fichiers dans un sous-répertoire .del / (et retour)

utilisation: del [-v] [-u] fichier (s)
       del [-v] -p [-r] [-d jours] [répertoire]
       del [-v] -l
options: -v mode verbeux
         -u fichier (s) non supprimé
         -p purger les fichiers supprimés [plus de -d jours]
         -r récursif (tous les sous-répertoires)
         -l liste les fichiers supprimés
exemples: del * .tmp # supprimer tous les fichiers * .tmp
          del -u project.pl # undelete project.pl
          del -vprd 2 # purge verbeuse les fichiers supprimés datant de plus de 2 jours
Framstag
la source
0

Dans KDE 4.14.8, j’utilisais la commande suivante pour déplacer les fichiers dans la corbeille (comme si elle avait été supprimée dans Dolphin):

kioclient move path_to_file_or_directory_to_be_removed trash:/

Annexe I: J'ai découvert la commande avec

    ktrash --help
...
    Note: to move files to the trash, do not use ktrash, but "kioclient move 'url' trash:/"

Annexe II: la fonction (puis la source dans votre .bashrc)

function Rm {
    if [[ "$1" == '--help' ]] ; then
        echo 'USAGE:'
        echo 'Rm --help # - show help'
        echo 'Rm file1 file2 file3 ...'
        echo 'Works for files and directories'
        return
    fi
    for i in "$@" ;
    do
        kioclient move $i trash:/ && echo "$i was trashed"
    done
}
utilisateur3804598
la source