「rm」をゴミ箱に移動する


54

ファイルを削除する代わりに、特別な「ゴミ箱」の場所に移動するLinuxスクリプト/アプリケーションはありますか?私はこれを代わりにしたいと思いますrm(後者をエイリアスすることさえあります。賛否両論があります)。

「ゴミ箱」とは、特別なフォルダを意味します。シングルmv $* ~/.trashは最初のステップですが、理想的には、古いゴミ箱に上書きせずに同じ名前の複数のファイルをゴミ箱に入れ、単純なコマンド(元に戻す)で元の場所にファイルを復元できます。さらに、再起動時にゴミ箱が自動的に空になった場合(または、無限の成長を防ぐための同様のメカニズム)に便利です。

これに対する部分的な解決策は存在しますが、特に「復元」アクションは簡単ではありません。グラフィカルシェルのゴミ箱システムに依存しない既存のソリューションはありますか?

(余談ですが、頻繁なバックアップとVCSを使用するのではなく、このアプローチが正当であるかどうかについては議論が続いています。これらの議論には重要な点がありますが、私の要望にはまだニッチがあると思います。)


4
これは、ファイルをゴミ箱に移動するためのスーパーユーザーの質問2つのコマンドに関連している可能性があります。違いは何ですか?gvfs-trash過去に使用したことがありますが、好奇心を刺激するまでコマンドラインから復元する必要はありませんでした。リンクされた質問への答えは役に立つかもしれません。
ephsmith

1
@ephsmithありがとう、良いリンク。ただし、これらのアプローチの問題は、特定のデスクトップシェル(ここでは正しい用語は何ですか)実装にバインドされていることです。これは避けたいものです。
コンラッドルドルフ

1
任意のファイルシステムからファイルを〜に意図的に移動していますか?いつかは、本当にリモートのサーバーからsshfsでマウントされたディレクトリにある4GB isoイメージを削除するかもしれないからです。
ミーシャアレフィエフ

1
@Mischa正直に言うと、そんなに考えたことはありませんでした。ただし、通常のユーザーの権限で動作する必要があるため、ターゲットは書き込み可能な場所である必要があり、あまり多くの構成を必要としないはずです。
コンラッドルドルフ

3
以下の回答で概説されているソリューションなど、必要なことは何でも行いますが、rmという名前は付けないでください。他の人が指摘したように、標準コマンドの名前を変更/再利用すると、他のシステムで習慣的に使用しようとすると脆弱になりますが、予期しない結果が発生したときにシステム/アカウントを使用する他の人(おそらくあなたを支援する)にも問題が発生します。
ジョー

回答:


37

freedesktop.orgにはゴミ箱の仕様(ドラフト)があります。明らかに、デスクトップ環境によって通常実装されるものです。

コマンドラインの実装はtrash-cliです。よく見ることなく、あなたが望む機能を提供するようです。そうでない場合は、これが部分的な解決策にすぎないことを教えてください。

置き換え/エイリアスとしてプログラムを使用するrmことに関する限り、それを行わない正当な理由があります。私にとって最も重要なのは:

  • プログラムは、すべてrmのオプションを理解/処理し、それに応じて行動する必要があります
  • 他の人のシステムで作業している場合、「新しいrm」のセマンティクスに慣れ、致命的な結果を伴うコマンドを実行するリスクがあります

削除されたすべてのファイルをLD_PRELOADを介してごみ箱に自動的に移動するlibtrashもあります(ただし、いくつかのバグがあるようです)。Autotrashは、ごみを簡単にきれいにするのに役立ちます。
ジョフェル

私はrmを使う習慣を身に付けることについて疑問に思っています。残念ながら、私はすでに習慣になっています。
コンラッドルドルフ

@jofel:libtrashには素晴らしいコンセプトがあります。他のアプローチよりも数層深い。それはバグがあるのは残念です(そして、あまりアクティブではないようです)。
zpea

4
@KonradRudolph:rm(置換されたもの)は実際には何も削除しないという事実に慣れることを意味しました。もちろん、rm自体を使用することは悪いことでも、慣れることでもありません。
zpea

4
私はこのソリューションをrm使用してしまい、それを誤って使用できないように無効にしました(/bin/rm本当に必要な場合はまだあります)。
コンラッドルドルフ


7

前の回答では、コマンドtrash-cliとに言及していますrmtrash。Ubuntu 18.04ではこれらのどちらもデフォルトでは見つかりませんが、コマンドgioはあります。コマンドgio help trash出力:

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

Move files or directories to the trash.

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

gio trash FILENAMEコマンドラインでテストしましたが、ファイルブラウザーでファイルを選択して[DEL]ボタンをクリックしたように機能します。ファイルはデスクトップの[ゴミ箱]フォルダーに移動されます。(この-fオプションを使用しなかった場合でも、コマンドは確認を求めません。)

この方法でファイルを削除することは元に戻すことができますrmrm -i、安全のために再定義し、各削除を確認するよりも便利ですが、誤って削除すべきでないことを確認した場合は運が悪くなります。

alias tt='gio trash'エイリアス定義ファイルに追加しました。ttTo Trashのニーモニックです。

2018-06-27の編集時に追加:サーバーマシンでは、ゴミ箱に相当するものはありません。仕事をする次のBashスクリプトを作成しました。デスクトップマシンではgio trash、を使用し、他のマシンでは、パラメーターとして指定されたファイルを、作成したゴミ箱ディレクトリに移動します。スクリプトは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

5

これを行うrmtrashという小さなユーティリティがあります。

-rまたはのような-fパラメータには応答しないようです(基本的にファイル/ディレクトリを〜/ .Trashディレクトリに移動しているように見えます)が、同じ名前のファイルを上書きしません(「コピー」を追加します)同様の名前のファイル/ディレクトリ)。

brewでインストールするには

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

github.com/nateshmbhat/rm-trash 。"rm-trash"は、重複したファイル名と再帰的な削除も処理します。見てみな。
ナテシュバート18

4

これは、名前の衝突に対処し、1秒に複数のファイルを削除しない限り、同じパス上で複数の削除されたファイルを許可する、迅速で汚いゴミシステムです。

警告:このコードをブラウザに直接入力しました。おそらく壊れています。実稼働データには使用しないでください。

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
)

既知の問題点:

  • 同じファイルを同時に数回削除しようとすると、うまく対処しません。
  • ごみ箱ディレクトリは巨大になる可能性があり、ファイルはハッシュの最初の数桁に基づいてサブディレクトリにディスパッチされる必要があります。
  • trashファイル名の改行に対応する必要がuntrashありgrepますが、メタデータファイルでは改行がエスケープされないため依存しません。

2

move_to_trash関数を定義することから始めます。

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

次に、そのエイリアスrm

alias rm='move_to_trash'

次のrmように、バックスラッシュでエスケープすることでいつでもold を呼び出すことができます\rm

再起動時にゴミ箱ディレクトリを空にする方法はわかりません(システムによっては、rc*スクリプトを調べる必要があるかもしれません)が、cron定期的にディレクトリを空にするタスクを作成することも価値があります。


2
残念ながら、それは簡単な部分でした...:/
コンラッドルドルフ

このスクリプトは、隠されたディレクトリに、それが存在するディレクトリを含む各ファイルのテキストファイルを作成することもできます。復元スクリプトは、古い場所を読み取って元に戻すことができます。
ephsmith

また、同じ名前の複数の削除されたファイルがゴミ箱ディレクトリで衝突する危険性があり、最後の「削除された」ファイルのみが回復できるように生き残ります。
キラーミスト

@killermist、はい。もちろん、移動コマンドを使用して追加の操作を行う必要があります。「ごみ箱」ファイルに任意の名前を付け、元のパスを保持します:| これはすべて「なぜホイールを再作成するのか」という悲鳴です。この問題には既存の解決策があります。
ephsmith

また、別のエイリアス名を使用します。エイリアスなしで別のマシンで作業し、1回の呼び出しでrmファイルを送信します。delより良い選択かもしれません。
グレンジャックマン

1

私のデルを使用できます:

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

delは、.del /サブディレクトリ内のファイルを移動します

使用法:del [-v] [-u]ファイル
       del [-v] -p [-r] [-d days] [ディレクトリ]
       del [-v] -l
オプション:-v詳細モード
         -uファイルの削除を取り消します
         -p削除されたファイルをパージする[-d日より古い]
         -r recursive(すべてのサブディレクトリ)
         -l削除されたファイルをリストします
例:del * .tmp#すべての* .tmpファイルを削除
          del -u project.pl#project.plを元に戻す
          del -vprd 2#2日以上経過した削除済みファイルの詳細なパージ

0

KDE 4.14.8では、次のコマンドを使用してファイルをゴミ箱に移動しました(まるでDolphinで削除されたかのように)。

kioclient move path_to_file_or_directory_to_be_removed trash:/

付録I:コマンドについて見つけた

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

付録II:関数(.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
}
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.