Bewegen Sie `rm` in den Papierkorb

54

Gibt es ein Linux-Skript / eine Linux-Anwendung, das / die Dateien nicht löscht, sondern an einen bestimmten Speicherort im Papierkorb verschiebt? Ich möchte dies als Ersatz für rm(vielleicht sogar als Alias ​​für Letzteres; es gibt Vor- und Nachteile dafür).

Mit "Papierkorb" meine ich einen speziellen Ordner. Eine einzelne mv $* ~/.trashDatei ist ein erster Schritt, aber im Idealfall sollten Sie auch mehrere Dateien mit demselben Namen in den Papierkorb werfen, ohne ältere, in den Papierkorb geworfene Dateien zu überschreiben. Außerdem können Sie Dateien mit einem einfachen Befehl (einer Art „Rückgängig“) an ihrem ursprünglichen Speicherort wiederherstellen . Außerdem wäre es schön, wenn der Papierkorb beim Neustart automatisch geleert würde (oder ein ähnlicher Mechanismus, um endloses Wachstum zu verhindern).

Hierfür gibt es Teillösungen, aber insbesondere die Aktion "Wiederherstellen" ist nicht trivial. Gibt es dafür Lösungen, die sich nicht auf ein Müllsystem aus einer grafischen Shell stützen?

(Abgesehen davon gab es endlose Diskussionen darüber, ob dieser Ansatz gerechtfertigt ist, anstatt häufige Backups und VCS zu verwenden. Obwohl diese Diskussionen einen Sinn haben, glaube ich, dass es noch eine Nische für meine Anfrage gibt.)

Konrad Rudolph
quelle
4
Dies kann mit der SuperUser-Frage Zwei Befehle zum Verschieben von Dateien in den Papierkorb zusammenhängen. Was ist der Unterschied? . Ich habe gvfs-trashin der Vergangenheit verwendet, musste aber nie von der Kommandozeile wiederherstellen, bis Sie meine Neugier geweckt haben. Die Antwort auf die verknüpfte Frage kann hilfreich sein.
Ephsmith
1
@ephsmith Danke, guter Link. Das Problem bei diesen Ansätzen ist jedoch, dass sie an bestimmte Desktop-Shell-Implementierungen gebunden sind (was ist hier der richtige Begriff?), Was ich vermeiden möchte.
Konrad Rudolph
1
Ist das Verschieben von Dateien von einem Dateisystem zu Ihrer Absicht? Weil Sie eines Tages möglicherweise ein 4-GB-ISO-Image löschen, das sich in einem Verzeichnis befindet, das mit sshfs von einem wirklich entfernten Server gemountet wurde.
Mischa Arefiev
1
@ Mischa Um ehrlich zu sein, habe ich nicht so viel darüber nachgedacht. Das heißt, es sollte mit den üblichen Benutzerrechten funktionieren, daher muss das Ziel ein Ort sein, der beschreibbar ist und nicht zu viel Konfiguration erfordert.
Konrad Rudolph
3
Tun Sie, was Sie wollen, wie in den Antworten unten beschrieben, aber nennen Sie es nicht rm. Wie bereits von anderen erwähnt, sind Sie durch das Umbenennen / Umbenennen von Standardbefehlen anfällig, wenn Sie gewöhnlich versuchen, sie auf anderen Systemen zu verwenden. Wenn jedoch unerwartete Ergebnisse auftreten, kann dies auch zu Problemen für andere Benutzer (die Ihnen möglicherweise behilflich sind) führen.
Joe

Antworten:

37

Es gibt eine Spezifikation (Entwurf) für den Papierkorb auf freedesktop.org. Es ist anscheinend das, was normalerweise in Desktop-Umgebungen implementiert wird.

Eine Kommandozeilenimplementierung wäre trash-cli . Ohne genauer hinzuschauen, scheint es die Funktionalität zu bieten, die Sie wollen. Wenn nicht, teilen Sie uns mit, inwieweit dies nur eine Teillösung ist.

Was die Verwendung eines Programms als Ersatz / Alias ​​für rmbetrifft, gibt es gute Gründe, dies nicht zu tun. Am wichtigsten für mich sind:

  • Das Programm muss alle rmOptionen verstehen / handhaben und entsprechend handeln
  • Es besteht die Gefahr, dass Sie sich an die Semantik Ihres "neuen RM" gewöhnen und Befehle mit schwerwiegenden Folgen ausführen, wenn Sie an den Systemen anderer Personen arbeiten
zpea
quelle
Es gibt auch libtrash, das alle gelöschten Dateien automatisch über LD_PRELOAD in den Papierkorb verschiebt (aber es scheint mehrere Fehler zu geben). Autotrash hilft, den Müll auf einfache Weise zu reinigen.
Jofel
Ich frage mich, ob ich es mir zur Gewohnheit gemacht habe, rm zu benutzen. Ich bin leider schon in der Gewohnheit.
Konrad Rudolph
@jofel: libtrash hat ein wirklich schönes konzept. Ein paar Schichten tiefer als die anderen Ansätze. Schade, dass es fehlerhaft ist (und nicht sehr aktiv zu sein scheint).
zpea
4
@KonradRudolph: Ich meinte, man gewöhnt sich daran, dass rm (der Ersetzte) eigentlich nichts löscht, so dass man weniger vorsichtig ist, da eine Wiederherstellung immer möglich ist. Natürlich ist es weder schlecht, rm selbst zu benutzen, noch gewöhnt man sich daran.
zpea
4
Am Ende habe ich diese Lösung verwendet und deaktiviert, rmsodass ich sie nicht versehentlich verwenden kann (es gibt immer noch einen /bin/rmFall, dass ich sie wirklich brauche).
Konrad Rudolph
9

Trash-cli ist eine Linux-Anwendung, die mit apt-get in Ubuntu oder yum in Fedora installiert werden kann. Mit dem Befehl trash listOfFileswird die angegebene in den Papierkorb verschoben.

namu
quelle
Zur Unterstützung dieses Vorschlags: apple.stackexchange.com/a/17637/37190
Ioannis Filippidis
7

Die vorherigen Antworten erwähnen Befehle trash-cliund rmtrash. Unter Ubuntu 18.04 wird keiner von beiden standardmäßig gefunden, aber der Befehl giolautet. Kommandier gio help trashAusgänge:

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

Move files or directories to the trash.

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

Ich habe es mit gio trash FILENAMEder Befehlszeile getestet und es funktioniert so, als hätte ich die Datei im Dateibrowser ausgewählt und auf die Schaltfläche ENTF geklickt: Die Datei wird in den Papierkorb des Desktops verschoben. (Der Befehl fordert keine Bestätigung an, obwohl ich die -fOption nicht verwendet habe .)

Das Löschen von Dateien auf diese Weise ist umkehrbar, aber bequemer rm, als rm -iaus Sicherheitsgründen neu zu definieren und jeden Löschvorgang zu bestätigen. Wenn Sie versehentlich einen Löschvorgang bestätigen, den Sie nicht haben sollten, haben Sie dennoch Pech.

Ich alias tt='gio trash'habe meiner Aliasdefinitionsdatei hinzugefügt . ttist eine Mnemonik für To Trash.

Beim Bearbeiten am 27.06.2018 hinzugefügt: Auf Servern gibt es kein Äquivalent zu einem Papierkorbverzeichnis. Ich habe das folgende Bash-Skript geschrieben, das die Arbeit erledigt. Auf Desktop-Computern, die es verwendet gio trash, und auf anderen Computern werden die als Parameter angegebenen Dateien in ein von ihm erstelltes Papierkorbverzeichnis verschoben. Skript am 05.09.2019 aktualisiert.

#!/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
quelle
5

Es gibt ein kleines Hilfsprogramm namens rmtrash, das dies tut.

Es scheint nicht auf params wie -roder zu reagieren -f(es scheint im Wesentlichen nur das Verschieben der Datei / des Verzeichnisses in das ~ / .Trash-Verzeichnis zu sein), aber es überschreibt keine Dateien mit demselben Namen (es hängt "Kopieren" an gleichnamige Dateien / Verzeichnisse).

Mit brauen zu installieren

brew install rmtrash
alias rm='rmtrash' >> ~/.bashrc
FreePender
quelle
github.com/nateshmbhat/rm-trash . "rm-trash" behandelt auch doppelte Dateinamen und rekursive Löschvorgänge. Hör zu.
Natesh Bhat
4

Hier ist ein schnelles und unsauberes Papierkorbsystem, das mit Namenskonflikten umgeht und sogar mehrere gelöschte Dateien auf demselben Pfad zulässt, solange Sie nicht mehr als eine Datei pro Sekunde löschen.

Warnung: Ich habe diesen Code direkt in meinen Browser eingegeben. Es ist wahrscheinlich kaputt. Verwenden Sie es nicht für Produktionsdaten.

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
)

Bekannte Probleme:

  • Kommt nicht zügig zurecht, wenn Sie versuchen, dieselbe Datei mehrmals gleichzeitig zu löschen.
  • Das Papierkorbverzeichnis kann sehr groß werden. Die Dateien sollten in Unterverzeichnissen abgelegt werden, die auf den ersten Ziffern des Hashs basieren.
  • trashsollte mit Zeilenumbrüchen in Dateinamen umgehen, untrashtut dies aber nicht, da sie darauf angewiesen sind grepund die Zeilenumbrüche nicht in der Metadatendatei maskiert werden.
Gilles 'SO - hör auf böse zu sein'
quelle
2

Definieren Sie zunächst eine move_to_trashFunktion:

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

Dann alias rmdazu:

alias rm='move_to_trash'

Sie können immer alt rufen , rmindem sie es mit einem Backslash, wie dies zu entkommen: \rm.

Ich weiß nicht, wie ich das Papierkorbverzeichnis beim Neustart leeren soll (abhängig von Ihrem System müssen Sie möglicherweise die rc*Skripte überprüfen), aber es könnte sich auch lohnen, eine cronAufgabe zu erstellen , die das Verzeichnis regelmäßig leert.

rahmu
quelle
2
Leider war das der einfache Teil…: /
Konrad Rudolph
Dieses Skript könnte auch eine Textdatei in einem versteckten Verzeichnis für jede Datei erstellen, die das Verzeichnis enthält, in dem es sich befand. Ein Wiederherstellungsskript könnte den alten Speicherort lesen und ihn zurück verschieben.
Ephsmith
Dies birgt auch die Gefahr, dass mehrere gelöschte Dateien mit demselben Namen im Papierkorbverzeichnis kollidieren und nur die letzte "gelöschte" Datei überlebt, um wiederhergestellt zu werden.
Killermist
@ Killermist, ja. Natürlich müsste man mit dem Befehl move noch etwas anderes machen. Benennen Sie die "verworfene" Datei wie gewünscht und behalten Sie den ursprünglichen Pfad bei: | Das alles schreit "warum das Rad neu erschaffen". Für dieses Problem gibt es bereits Lösungen.
Ephsmith
Verwenden Sie auch einen anderen Aliasnamen. Arbeiten Sie auf einem anderen Computer ohne Ihre Aliase, ein Anruf zu rmund los geht's. delkönnte eine bessere Wahl sein.
Glenn Jackman
1

Sie können meine del verwenden:

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

del verschiebt Dateien in ein .del / -Unterverzeichnis (und zurück)

Verwendung: del [-v] [-u] Datei (en)
       del [-v] -p [-r] [-d Tage] [Verzeichnis]
       del [-v] -l
Optionen: -v Ausführlicher Modus
         -u Datei (en) wiederherstellen
         -p löscht gelöschte Dateien [älter als -d Tage]
         -r rekursiv (alle Unterverzeichnisse)
         -l liste gelöschte Dateien auf
Beispiele: del * .tmp # Löscht alle * .tmp-Dateien
          del -u project.pl # undelete project.pl
          del -vprd 2 # verbose löscht gelöschte Dateien, die älter als 2 Tage sind
Framstag
quelle
0

In KDE 4.14.8 habe ich den folgenden Befehl verwendet, um Dateien in den Papierkorb zu verschieben (als ob sie in Dolphin entfernt worden wären):

kioclient move path_to_file_or_directory_to_be_removed trash:/

Anhang I: Ich habe über den Befehl mit

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

Anhang II: Die Funktion (dann in Ihrer .bashrc-Datei ausgeben)

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
}
user3804598
quelle