`rm`을 휴지통으로 이동


54

파일을 삭제하는 대신 특별한 "휴지통"위치로 옮기는 Linux 스크립트 / 응용 프로그램이 있습니까? 나는 이것을 대신하기를 원합니다 rm(후자를 별명으로 할 수도 있습니다; 그것에 대한 장단점이 있습니다).

“휴지통”이란 특별한 폴더를 의미합니다. 단일 mv $* ~/.trash단계는 첫 번째 단계이지만 이상적으로는 오래된 휴지통 파일을 덮어 쓰지 않고 동일한 이름의 여러 파일을 휴지통으로 처리 하고 간단한 명령 (“실행 취소”) 을 사용 하여 파일을 원래 위치 로 복원 할 수 있어야 합니다. 또한 재부팅시 휴지통이 자동으로 비워지면 (또는 끝없는 성장을 막는 유사한 메커니즘) 좋을 것입니다.

이에 대한 부분 솔루션이 존재하지만 특히 "복원"작업은 쉽지 않습니다. 그래픽 쉘의 휴지통 시스템에 의존하지 않는 기존 솔루션이 있습니까?

(제외 적으로, 빈번한 백업과 VCS를 사용하는 대신이 접근 방식이 정당화되는지에 대한 끝없는 논의가있었습니다. 이러한 논의에는 요점이 있지만, 여전히 내 요청에 틈새가 있다고 생각합니다.)


4
파일을 휴지통으로 옮기는 수퍼 유저 질문 두 명령 과 관련이있을 수 있습니다 . 차이점이 뭐야? . 내가 사용했던 gvfs-trash과거에,하지만 당신은 나의 호기심을 촉발 때까지 명령 줄에서 복원 할 필요가 없었어요. 연결된 질문에 대한 답변이 도움이 될 수 있습니다.
ephsmith

1
@ephsmith 감사합니다, 좋은 링크. 그러나 이러한 접근법의 문제점은 특정 데스크탑 쉘 (여기서 올바른 용어는 무엇입니까?) 구현에 묶여 있다는 것입니다.
Konrad Rudolph

1
어떤 파일 시스템에서 ~ 의도적으로 파일을 옮기고 있습니까? 언젠가는 실제로 원격 서버에서 sshfs로 마운트 된 디렉토리에있는 4GB iso 이미지를 삭제할 수 있습니다.
Mischa Arefiev

1
@Mischa 솔직히 말해서, 나는 그것에 대해 많은 생각을하지 않았습니다. 즉, 일반적인 사용자 권한으로 작동해야하므로 대상은 쓰기 가능한 위치 여야하고 너무 많은 구성이 필요하지 않아야합니다.
Konrad Rudolph

3
아래 답변에 요약 된 솔루션과 같이 원하는 것을 수행 하지만 이름을 rm으로 지정 하지 마십시오 . 다른 사람들이 지적한 것처럼 표준 명령의 이름을 바꾸거나 용도를 바꾸면 습관적으로 다른 시스템에서 명령을 사용하려고 할 때 취약 해 지지만 예기치 않은 결과가 발생하면 다른 사람이 시스템 / 계정을 사용하여 문제를 일으킬 수 있습니다.
Joe

답변:


37

휴지통에 대한 사양 (안) freedesktop.org에가. 그것은 일반적으로 데스크탑 환경에 의해 구현되는 것입니다.

커맨드 라인 구현은 trash-cli 입니다. 자세히 살펴 보지 않으면 원하는 기능을 제공하는 것 같습니다. 그렇지 않다면 이것이 부분적인 해결책에 불과하다는 것을 알려주십시오.

대체 / 별칭으로 프로그램을 사용하는 한 rm, 그렇게하지 않는 좋은 이유가 있습니다. 나에게 가장 중요한 것은 :

  • 프로그램은 모든 rm옵션 을 이해 / 처리 하고 그에 따라 행동해야합니다.
  • 다른 사람의 시스템에서 작업 할 때 "새 rm"의 의미에 익숙해지고 치명적인 결과로 명령을 수행 할 위험이 있습니다.

LD_PRELOAD를 통해 삭제 된 모든 파일을 휴지통으로 자동으로 이동 시키는 libtrash 도 있습니다 (그러나 몇 가지 버그가있는 것 같습니다). 자동 휴지통은 쉽게 쓰레기를 청소하는 데 도움이됩니다.
jofel

나는 생활 습관을 얻는 것에 대해 궁금합니다. 안타깝게도 이미 버릇이 있습니다.
Konrad Rudolph

@ jofel : libtrash에는 정말 좋은 개념이 있습니다. 다른 접근 방식보다 몇 층 더 깊습니다. 안타깝습니다 (매우 활동적으로 보이지 않습니다).
zpea

4
@ KonradRudolph : 나는 rm (대체 된 것)이 실제로 아무것도 삭제하지 않는다는 사실에 익숙해 져서 복원이 항상 가능하므로 덜 조심합니다. 물론 rm 자체를 사용하는 것은 나쁜 일이 아니며 익숙하지도 않습니다.
zpea

4
나는이 솔루션을 사용하고 결국 비활성화 rm하여 실수로 사용할 수 없습니다 ( /bin/rm실제로 필요한 경우가 있습니다).
Konrad Rudolph


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휴지통에 대한 니모닉입니다.

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 디렉토리로 옮기는 것 같습니다 ).하지만 같은 이름의 파일을 무시하지는 않습니다 ( "Copy" 같은 이름의 파일 / 디렉토리).

추출과 함께 설치하려면

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

github.com/nateshmbhat/rm-trash . "rm-trash"는 중복 파일 이름 및 재귀 삭제도 처리합니다. 확인 해봐.
Natesh bhat

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다음과 같이 백 슬래시로 이스케이프 처리하여 항상 old 를 호출 할 수 있습니다 \rm.

재부팅 할 때 휴지통 디렉토리를 비우는 방법을 모르지만 (시스템에 따라 rc*스크립트 를 살펴 봐야 할 수도 있음) cron디렉토리를 주기적으로 비우는 작업 을 만드는 것이 좋습니다 .


2
불행히도, 그것은 쉬운 부분이었습니다 ... : /
Konrad Rudolph

이 스크립트는 또한 자신이 있던 디렉토리를 포함하는 각 파일에 대해 숨겨진 디렉토리에 텍스트 파일을 작성할 수 있습니다. 복원 스크립트는 이전 위치를 읽고 다시 이동할 수 있습니다.
ephsmith

또한 동일한 이름을 가진 여러 개의 삭제 된 파일이 휴지통 디렉토리에 충돌 할 수 있으며 마지막 "삭제 된"파일 만 복구 할 수 있습니다.
킬러 미스트

@killermist입니다. 물론 이동 명령으로 추가 작업을 수행해야합니다. 원하는대로 "휴지통"파일의 이름을 지정하고 원래 경로를 유지하십시오. | 이 모든 것이 "바퀴를 다시 만드는 이유"를 외칩니다. 이 문제에 대한 기존 솔루션이 있습니다.
ephsmith

또한 다른 별명 이름을 사용하십시오. 별명없이 다른 컴퓨터에서 작업하고 한 번의 호출로 rm파일을 이동합니다. del더 나은 선택 일 수 있습니다.
glenn jackman

1

내 델을 사용할 수 있습니다 :

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

del은 .del / 서브 디렉토리에서 파일을 이동시킵니다 (그리고 뒤로)

사용법 : del [-v] [-u] 파일
       del [-v] -p [-r] [-d 일] [디렉토리]
       델 [-v] -l
옵션 : -v 상세 모드
         -u 파일 삭제 취소
         -p 삭제 된 파일을 제거합니다 [-d 일보다 오래된]
         -r 재귀 (모든 하위 디렉토리)
         -l 삭제 된 파일 목록
예 : del * .tmp # 모든 * .tmp 파일 삭제
          del -u project.pl # 삭제 취소 project.pl
          del -vprd 2 # 2 일 이상 지난 삭제 된 파일 삭제

0

KDE 4.14.8에서는 다음 명령을 사용하여 파일을 휴지통으로 옮겼습니다 (돌핀에서 제거 된 것처럼).

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.