Заставить `rm` перейти в корзину


54

Существует ли сценарий / приложение для Linux, которое вместо удаления файлов перемещает их в специальную «корзину»? Я хотел бы это как замену rm(может быть, даже псевдоним последнего; есть плюсы и минусы для этого).

Под «мусором» я подразумеваю специальную папку. Одиночный mv $* ~/.trashфайл - это первый шаг, но в идеале он также должен обрабатывать удаление нескольких файлов с одним и тем же именем без перезаписи старых загруженных файлов и позволять восстанавливать файлы в их исходное местоположение с помощью простой команды (своего рода «отмена»). Кроме того, было бы неплохо, если бы мусор автоматически очищался при перезагрузке (или аналогичном механизме, предотвращающем бесконечный рост).

Частичные решения для этого существуют, но, в частности, действие «восстановить» не тривиально. Существуют ли какие-либо решения для этого, которые не основаны на мусорной системе из графической оболочки?

(Кроме того, были бесконечные дискуссии о том, оправдан ли этот подход, а не об использовании частых резервных копий и VCS. Хотя в этих дискуссиях есть смысл, я считаю, что для моего запроса еще есть ниша).


4
Это может быть связано с вопросом SuperUser Две команды для перемещения файлов в корзину. Какая разница? , Я использовал gvfs-trashв прошлом, но никогда не нуждался в восстановлении из командной строки, пока вы не зажгли мое любопытство. Ответ на связанный вопрос может быть полезным.
ephsmith

1
@ephsmith Спасибо, хорошая ссылка. Однако проблема с этими подходами заключается в том, что они связаны с конкретными реализациями оболочки рабочего стола (каков здесь правильный термин?), Чего я хочу избежать.
Конрад Рудольф

1
Перенос файлов из любой файловой системы в вашу ~ преднамеренную? Потому что однажды вы, возможно, удаляете ISO-образ 4 ГБ, находящийся в каталоге, смонтированном с помощью sshfs, с действительно удаленного сервера.
Миша Арефьев

1
@ Миша Если честно, я не особо задумывался над этим. Тем не менее, он должен работать с обычными правами пользователя, поэтому целью должна быть папка с возможностью записи и не требующая слишком много настроек.
Конрад Рудольф

3
Делайте все, что хотите, например решения, изложенные в ответах ниже, но не называйте это rm. Как отмечают другие, переименование / перепрофилирование стандартных команд оставляет вас уязвимыми, когда вы обычно пытаетесь использовать их в других системах, но это также создаст проблемы для любого другого (возможно, помогающего вам) использования вашей системы / учетной записи в случае непредвиденных результатов.
Джо

Ответы:


37

Существует спецификация (черновик) для мусора на freedesktop.org. Это, по-видимому, то, что обычно реализуется в настольных средах.

Реализация командной строки была бы trash-cli . Похоже, что если вы не посмотрите поближе, вы получите желаемую функциональность. Если нет, скажите нам, насколько это только частичное решение.

Что касается использования любой программы в качестве замены / псевдонима rm, есть веские причины не делать этого. Наиболее важными для меня являются:

  • Программа должна понимать / обрабатывать все rmпараметры и действовать соответственно
  • Есть риск привыкнуть к семантике вашего "нового rm" и выполнять команды с фатальными последствиями при работе на системах других людей.

Существует также libtrash, которая автоматически перемещает все удаленные файлы в корзину через LD_PRELOAD (но, похоже, в ней есть несколько ошибок). Autotrash помогает легко очистить мусор.
Джофель

Я задаюсь вопросом о том, как привыкнуть употреблять вещи. К сожалению, я уже привык.
Конрад Рудольф

@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опцию.)

Удаление файлов таким образом , является обратимым, в то же время более удобно , чем переопределение rmбыть rm -iдля безопасности и того , чтобы подтвердить удаление каждого, который по- прежнему оставляет вас не повезло , если вы случайно подтверждения удаления вы не должны иметь.

Я добавил alias tt='gio trash'в мой файл определения псевдонимов; ttэто мнемоника To To 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(похоже, он просто перемещает каталог file / в каталог ~ / .Trash), но он не переопределяет файлы с тем же именем (он добавляет «Копировать» в одноименные файлы / каталоги).

Для установки с заваркой

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

github.com/nateshmbhat/rm-trash . "rm-trash", обрабатывает дубликаты имен файлов и рекурсивные удаления. Проверьте это.
Натеш бхат

4

Вот быстрая и грязная система мусора, которая справляется с конфликтами имен и даже позволяет нескольким удаленным файлам по одному и тому же пути, если вы не удаляете более одного файла в секунду.

Предупреждение: я набрал этот код прямо в своем браузере. Это вероятно сломано. Не используйте его для производственных данных.

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вытекания его с обратной косой черты, например: \rm.

Я не знаю, как сделать каталог мусора пустым при перезагрузке (в зависимости от вашей системы, вам, возможно, придется изучить rc*сценарии), но также может быть целесообразным создание cronзадачи, которая периодически очищает каталог.


2
К сожалению, это было легко ...: /
Конрад Рудольф

Этот сценарий может также создать текстовый файл в скрытом каталоге для каждого файла, в котором содержится каталог, в котором он находился. Сценарий восстановления может прочитать старое местоположение и переместить его обратно.
Эфсмит

Это также может привести к столкновению нескольких удаленных файлов с одним и тем же именем в каталоге корзины, и только последний «удаленный» может быть восстановлен.
убийца

@ killermist, да. Конечно, нужно было бы сделать что-то дополнительное с командой перемещения. Назовите «мусорный» файл как хотите и сохраните исходный путь: | Это все крики "зачем заново создавать колесо". Существуют решения этой проблемы.
Эфсмит

Также используйте другое псевдоним. Работайте на другом компьютере без ваших псевдонимов, один вызов rmи ваши файлы. delможет быть лучшим выбором.
Гленн Джекман

1

Вы можете использовать мой Del:

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

del перемещает файлы в подкаталоге .del / (и обратно)

использование: del [-v] [-u] файл (ы)
       del [-v] -p [-r] [-d дней] [каталог]
       del [-v] -l
опции: -v подробный режим
         -u восстановить файл (ы)
         -p очистить удаленные файлы [старше -d дней]
         -r рекурсивный (все подкаталоги)
         -l список удаленных файлов
примеры: del * .tmp # удалить все файлы * .tmp
          del -u project.pl # undelete 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
}
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.