Заставить `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.