Переместить `rm` в корзину

Переместить `rm` в корзину

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

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

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

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

решение1

Eстьспецификация (черновик) для Мусорана freedesktop.org. По-видимому, это то, что обычно реализуется в средах рабочего стола.

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

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

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

решение2

В предыдущих ответах упоминаются команды 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это мнемоническое обозначение для «отправить в корзину».

Добавлено в редактирование 27.06.2018:На серверных машинах нет эквивалента каталога для мусора. Я написал следующий скрипт Bash, который выполняет эту работу; на настольных машинах он использует gio trash, а на других машинах перемещает файл(ы), указанные в качестве параметра(ов), в созданный им каталог для мусора. Скрипт проверен на работоспособность; я сам постоянно им пользуюсь.Скрипт обновлен 12.04.2024.

#!/bin/bash

# move_to_trash
#
# Teemu Leisti 2024-04-12
#
# USAGE:
#
#   Move the file(s) given as argument(s) to the trash directory, if they are
#   not already there.
#
# RATIONALE:
#
#   The script is intended as a command-line equivalent of deleting a file or
#   directory from a graphical file manager. On hosts that implement the
#   FreeDesktop.org specification on trash directories (hereon called "the trash
#   specification"; see
#   https://specifications.freedesktop.org/trash-spec/trashspec-latest.html),
#   that action moves the target file(s) to a built-in trash directory, and that
#   is exactly what this script does.
#
#   On other hosts, this script uses a custom trash directory (~/.Trash/). The
#   analogy of moving a file to trash is not perfect, as the script does not
#   offer the functionalities of restoring a trashed file to its original
#   location or emptying the trash directory. Rather, it offers an alternative
#   to the 'rm' command, thereby giving the user the peace of mind that they can
#   still undo an unintended deletion before emptying the custom trash
#   directory.
#
# IMPLEMENTATION:
#
#   To determine whether it's running on a host that implements the trash
#   specification, the script tests for the existence of (a) the gio command and
#   (b) either directory $XDG_DATA_HOME/Trash/, or, if that environment variable
#   hasn't bee set, of directory ~/.local/share/Trash/. If the test yields true,
#   the script relies on calling 'gio trash'.
#
#   On other hosts:
#     - There is no built-in trash directory, so the script creates a custom
#       directory ~/.Trash/, unless it already exists. (The script aborts if
#       there is an existing non-directory ~/.Trash.)
#     - The script appends a millisecond-resolution timestamp to all the files
#       it moves to the custom trash directory, to both inform the user of the
#       time of the trashing, and to avoid overwrites.
#     - The user will have to perform an undo by commanding 'mv' on a file or
#       directory moved to ~/.Trash/.
#     - The user will have to empty the custom trash directory by commanding:
#           rm -rf ~/.Trash/* ~/.Trash/.*
#
#   The script will not choke on a nonexistent file. It outputs the final
#   disposition of each filename argument: does not exist, was already in trash,
#   or was moved to trash.
#
# COPYRIGHT WAIVER:
#
#   The author dedicates this Bash script to the public domain by waiving all of
#   their rights to the work worldwide under copyright law, including all
#   related and neighboring rights, to the extent allowed by law. You can copy,
#   modify, distribute, and perform the script, even for commercial purposes,
#   all without asking for permission.

if [ -z "$XDG_DATA_HOME" ] ; then
    xdg_trash_directory=$(realpath ~/.local/share/Trash/)
else
    xdg_trash_directory=$(realpath $XDG_DATA_HOME/Trash/)
fi

gio_command_exists=0
if $(command -v gio > /dev/null 2>&1) ; then
    gio_command_exists=1
fi

host_implements_trash_specification=0
if [[ -d "${xdg_trash_directory}" ]] && (( gio_command_exists == 1 )) ; then
    # Executing on a host that implements the trash specification.
    host_implements_trash_specification=1
    trash_directory="${xdg_trash_directory}"
else
    # Executing on other host, so attempt to use a custom trash directory.
    trash_directory=$(realpath ~/.Trash)
    if [[ -e "${trash_directory}" ]] ; then
        # It exists.
        if [[ ! -d "${trash_directory}" ]] ; then
            # But is not a directory, so abort.
            echo "Error: ${trash_directory} exists, but is not a directory."
            exit 1
        fi
    else
        # It does not exists, so create it.
        mkdir "${trash_directory}"
        echo "Created directory ${trash_directory}"
    fi
fi

# Deal with all filenames (a concept that covers names of both files and
# directories) given as arguments.
for file in "$@" ; do
    file_to_be_trashed=$(realpath -- "${file}")
    file_basename=$(basename -- "${file_to_be_trashed}")
    if [[ ! -e ${file_to_be_trashed} ]] ; then
        echo "does not exist:   ${file_to_be_trashed}"
    elif [[ "${file_to_be_trashed}" == "${trash_directory}"* ]] ; then
        echo "already in trash: ${file_to_be_trashed}"
    else
        # ${file_to_be_trashed} exists and is not yet in the trash directory,
        # so move it there.
        if (( host_implements_trash_specification == 1 )) ; then
            gio trash "${file_to_be_trashed}"
        else
            # Move the file to the custom trash directory, with a new name that
            # appends a millisecond-resolution timestamp to the original.
            head="${trash_directory}/${file_basename}"_TRASHED_ON_
            move_file_to="${head}$(date '+%Y-%m-%d_AT_%H-%M-%S.%3N')"
            while [[ -e "${move_file_to}" ]] ; do
                # Generate a new name with a new timestamp, as the previously
                # generated one denoted an existing file or directory. It's very
                # unlikely that this loop needs to be executed even once.
                move_file_to="${head}$(date '+%Y-%m-%d_AT_%H-%M-%S.%3N')"
            done
            # There is no file or directory named ${move_file_to}, so
            # we can use it as the move target.
            /bin/mv "${file_to_be_trashed}" "${move_file_to}"
        fi
        echo "moved to trash:   ${file_to_be_trashed}"
    fi
done

решение3

Trash-cliэто приложение linux, которое можно установить с помощью apt-get в Ubuntu или yum в Fedora. Использование команды trash listOfFilesпереместит указанное в корзину.

решение4

Начнем с определения move_to_trashфункции:

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

Тогда псевдоним rmк этому:

alias rm='move_to_trash'

Вы всегда можете вызвать old, rmэкранировав его обратной косой чертой, например: \rm.

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

Связанный контент