Make 'rm' move para o lixo

49

Existe um script / aplicativo Linux que, em vez de excluir arquivos, os move para um local especial de "lixeira"? Eu gostaria disso como um substituto para rm (talvez até aliasing este último; há prós e contras para isso).

Por "lixo" quero dizer uma pasta especial. Um único mv $* ~/.trash é o primeiro passo, mas idealmente isso também deve lidar com a lixeira de vários arquivos com o mesmo nome sem sobrescrever arquivos antigos da lixeira, e permitir restaurar arquivos para sua localização original com um simples comando ( uma espécie de "desfazer"). Além disso, seria bom se a lixeira fosse esvaziada automaticamente durante a reinicialização (ou um mecanismo semelhante para impedir o crescimento sem fim).

Soluções parciais para isso existem, mas a ação "restaurar" em particular não é trivial. Existem soluções existentes para isso que não dependem de um sistema de lixeira de uma casca gráfica?

(Como um aparte, tem havido discussões intermináveis sobre se esta abordagem é justificada, em vez de usar backups frequentes e VCS. Embora essas discussões tenham um ponto, acredito que ainda haja um nicho para o meu pedido.)

    
por Konrad Rudolph 11.07.2012 / 00:05

7 respostas

34

Existe uma especificação (rascunho) para a Lixeira no freedesktop.org. É aparentemente o que geralmente é implementado por ambientes de desktop.

Uma implementação de linha de comando seria trash-cli . Sem ter um olhar mais atento, parece fornecer a funcionalidade que você deseja. Se não, diga-nos até que ponto esta é apenas uma solução parcial.

No que diz respeito a usar qualquer programa como substituto / alias para rm , há boas razões para não fazer isso. O mais importante para mim é:

  • O programa precisaria entender / manipular todas as opções de rm e agir de acordo
  • Há o risco de se acostumar com a semântica do seu "novo rm" e executar comandos com consequências fatais ao trabalhar em sistemas de outras pessoas
por 11.07.2012 / 03:41
9

Trash-cli é uma aplicação linux que pode ser instalada usando o apt-get no Ubuntu ou no yum do Fedora. Usar o comando trash listOfFiles moverá o especificado para a sua lixeira.

    
por 14.02.2015 / 02:21
4

Aqui está um sistema de lixo rápido e sujo que lida com confrontos de nomes e até permite vários arquivos excluídos no mesmo caminho, desde que você não exclua mais de um arquivo por segundo.

Aviso: digitei esse código diretamente no meu navegador. Provavelmente está quebrado. Não use em dados de produção.

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
)

Problemas conhecidos:

  • Não funciona normalmente se você tentar excluir o mesmo arquivo várias vezes ao mesmo tempo.
  • O diretório da lixeira pode ficar enorme, os arquivos devem ser despachados em subdiretórios com base nos primeiros dígitos do hash.
  • trash deve lidar com novas linhas em nomes de arquivos, mas untrash não porque depende de grep e as novas linhas não são ignoradas no arquivo de metadados.
por 11.07.2012 / 03:37
4

Existe um pequeno utilitário chamado rmtrash que faz isso.

Ele não parece responder a parâmetros como -r ou -f (parece ser basicamente apenas mover o arquivo / diretório para o diretório ~ / .Trash), mas ele não substituirá os arquivos com o diretório mesmo nome (acrescenta "Copiar" a arquivos / diretórios com nomes semelhantes).

Para instalar com brew

brew install rmtrash
alias rm='rmtrash' >> ~/.bashrc
    
por 12.09.2014 / 20:24
4

As respostas anteriores mencionam os comandos trash-cli e rmtrash . Nenhum desses é encontrado por padrão no Ubuntu 18.04, mas o comando gio é. Comando gio help trash outputs:

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

Move files or directories to the trash.

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

Eu testei usando gio trash FILENAME na linha de comando, e funciona exatamente como eu selecionei o arquivo no navegador de arquivos e cliquei no botão DEL: o arquivo foi movido para a lixeira da área de trabalho pasta. (O comando não solicita confirmação, mesmo que eu não tenha usado a opção -f ).

Excluir arquivos dessa forma é reversível, embora seja mais conveniente do que redefinir rm como rm -i para segurança e ter que confirmar cada exclusão, o que ainda deixa você sem sorte se você acidentalmente confirmar uma exclusão. tem.

Adicionei alias tt='gio trash' ao meu arquivo de definições de alias; tt é um mnemônico para a lixeira.

Adicionado em edição em 2018-06-27: Em máquinas servidoras, não há equivalente de um diretório de lixeira. Eu escrevi um script Bash que faz o trabalho; em máquinas desktop, usa gio trash .

#!/bin/bash
# move-to-trash

# Teemu Leisti 2018-07-08

# This script moves the files given as arguments to the trash directory, if they
# are not already there. It works both on (Ubuntu) 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 functionalities of restoring a trashed file to
# its original location nor of emptying the trash directory; rather, it is an
# alternative to the 'rm' command that offers the user the peace of mind that
# they can still undo an unintended deletion before they empty the trash
# directory.
#
# To determine whether it's running on a desktop host, the script tests for the
# existence of directory ~/.local/share/Trash. In case it is, the script relies
# on the 'gio trash' command.
#
# When not running on a desktop host, there is no built-in trash directory, so
# the first invocation of the script creates one: ~/.Trash/. It will not
# overwrite an existing file in that directory; instead, in case a file given as
# an argument already exists in the custom trash directory, the script first
# appends a timestamp to the filename, with millisecond resolution, such that no
# existing file will be overwritten.
#
# 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 the trash.


# Exit on using an uninitialized variable, and on a command returning an error.
# (The latter setting necessitates appending " || true" to those arithmetic
# calculations that can result in a value of 0, lest bash interpret the result
# as signalling an error.)
set -eu

is_desktop=0

if [[ -d ~/.local/share/Trash ]] ; 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
            move_to_abspath="$trash_dir_abspath/$file_basename"
            while [[ -e "$move_to_abspath" ]] ; do
                move_to_abspath="$trash_dir_abspath/$file_basename-"$(date '+%Y-%m-%d-at-%H:%M:%S.%3N')
            done
            # While we're reasonably sure that the file at $move_to_abspath does not exist, we shall
            # use the '-f' (force) flag in the 'mv' command anyway, to be sure that moving the file
            # to the trash directory is successful even in the extremely unlikely case that due to a
            # run condition, some other thread has created the file $move_to_abspath after the
            # execution of the while test above.
            /bin/mv -f "$file_abspath" "$move_to_abspath"
        fi
        echo "moved to trash:   $file_abspath"
    fi
done
    
por 22.05.2018 / 11:12
2

Comece definindo uma função move_to_trash :

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

Em seguida, alias rm para isso:

alias rm='move_to_trash'

Você sempre pode ligar para o antigo rm escapando com uma barra invertida, assim: \rm .

Eu não sei como deixar o diretório de lixo vazio na reinicialização (dependendo do seu sistema, você pode ter que olhar para os scripts rc* ), mas também pode valer a pena criar uma tarefa cron que esvazia o diretório periodicamente.

    
por 11.07.2012 / 00:10
1

Você pode usar meu del:

link

del move arquivos em um subdiretório .del (e de volta)

usage: del [-v] [-u] file(s)
       del [-v] -p [-r] [-d days] [directory]
       del [-v] -l
options: -v   verbose mode
         -u   undelete file(s)
         -p   purge deleted files [older than -d days]
         -r   recursive (all subdirectories)
         -l   list deleted files
examples: del *.tmp         # delete all *.tmp files
          del -u project.pl # undelete project.pl
          del -vprd 2       # verbose purge deleted files older than 2 days
    
por 23.12.2016 / 22:48

Tags