web-dev-qa-db-fra.com

Faire passer `rm` dans la corbeille

Existe-t-il un script/une application Linux qui, au lieu de supprimer des fichiers, les déplace vers un emplacement spécial "poubelle"? Je voudrais que cela remplace rm (peut-être même alias ce dernier; il y a des avantages et des inconvénients pour cela).

Par "poubelle", je veux dire un dossier spécial. Un seul mv $* ~/.trash est une première étape, mais dans l'idéal, cela devrait également gérer la corbeille de plusieurs fichiers du même nom sans écraser les fichiers plus anciens et permettre restaurer les fichiers à leur emplacement d'origine avec une simple commande (une sorte de "annuler"). De plus, ce serait bien si la corbeille était 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 pour cela qui ne reposent pas sur un système de corbeille à partir d'un shell graphique?

(En passant, il y a eu des discussions sans fin pour savoir si cette approche est justifiée, plutôt que d'utiliser des sauvegardes fréquentes et VCS. Bien que ces discussions aient un point, je pense qu'il y a encore une niche pour ma demande.)

55
Konrad Rudolph

Il y a spécification (brouillon) pour la corbeille sur freedesktop.org. C'est apparemment ce qui est généralement implémenté par les environnements de bureau.

Une implémentation en ligne de commande serait trash-cli . Sans avoir regardé de plus près, il semble offrir 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 n'importe quel programme comme remplacement/alias pour 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 les options de rm et agir en conséquence
  • Il a le risque de s'habituer à la sémantique de votre "nouveau rm" et d'exécuter des commandes aux conséquences fatales lorsque vous travaillez sur les systèmes d'autres personnes
37
zpea

Les réponses précédentes mentionnent les commandes trash-cli et rmtrash. Aucun de ceux-ci n'est trouvé par défaut sur Ubuntu 18.04, mais la commande gio l'est. Commandant gio help trash les sorties:

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é en utilisant gio trash FILENAME sur la ligne de commande, et cela fonctionne exactement comme j'avais sélectionné le fichier dans le navigateur de fichiers et cliqué sur le bouton DEL: le fichier est déplacé vers le dossier Corbeille du bureau. (La commande ne demande pas de confirmation même si je n'ai pas utilisé le -f option.)

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

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

Ajouté lors de l'édition du 27/06/2018: Sur les machines serveurs, il n'y a 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 machines, déplace le ou les fichiers donnés en paramètre 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
9
Teemu Leisti

Trash-cli est une application Linux qui peut être installée en utilisant apt-get dans Ubuntu ou yum dans Fedora. Utilisation de la commande trash listOfFiles déplacera le spécifié dans votre corbeille.

9
namu

Voici un système de corbeille rapide et sale qui résout les conflits de noms et autorise 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 fonctionne pas correctement si vous essayez de supprimer plusieurs fois le même fichier simultanément.
  • Le répertoire de la corbeille peut devenir énorme, les fichiers doivent être distribués dans des sous-répertoires basés sur les premiers chiffres du hachage.
  • trash devrait gérer les sauts de ligne dans les noms de fichiers, mais untrash ne le fait pas car il repose sur grep et les sauts de ligne ne sont pas échappés dans le fichier de métadonnées.

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

Il ne semble pas répondre aux paramètres tels que -r ou -f (il semble essentiellement déplacer le fichier/répertoire vers le répertoire ~/.Trash), mais il ne remplacera pas les fichiers portant le même nom (il ajoute "Copier" aux fichiers/répertoires de même nom).

Pour installer avec brew

brew install rmtrash
alias rm='rmtrash' >> ~/.bashrc
4
FreePender

Commencez par définir un move_to_trash une fonction:

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

Puis alias rm à cela:

alias rm='move_to_trash'

Vous pouvez toujours appeler l'ancien rm en l'échappant avec une barre oblique inverse, comme ceci: \rm.

Je ne sais pas comment vider le répertoire de la corbeille au redémarrage (selon votre système, vous devrez peut-être consulter le rc* scripts), mais il pourrait également être utile de créer une tâche cron qui vide périodiquement le répertoire.

2
rahmu

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) à supprimer 
 -p purge 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 # supprime tous les fichiers * .tmp 
 del -u project.pl # undelete project .pl 
 del -vprd 2 # purge verbeuse fichiers supprimés de plus de 2 jours 
1
Framstag

Dans KDE 4.14.8, j'ai utilisé la commande suivante pour déplacer les fichiers dans la corbeille (comme s'ils avaient été supprimés dans Dolphin):

kioclient move path_to_file_or_directory_to_be_removed trash:/

Annexe I: J'ai trouvé 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 sourcez-la 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
}
0
user3804598