ย้าย `rm` ไปที่ถังขยะ


54

มี Linux สคริปต์ / แอปพลิเคชันซึ่งแทนที่จะลบไฟล์ย้ายพวกเขาไปยังตำแหน่ง "ขยะ" พิเศษหรือไม่? ฉันต้องการสิ่งนี้แทนrm(อาจเป็นนามแฝงหลังมีข้อดีและข้อเสียสำหรับการที่)

โดย“ ถังขยะ” ฉันหมายถึงโฟลเดอร์พิเศษ เดียวmv $* ~/.trashเป็นขั้นตอนแรก แต่นึกคิดนี้ควรจัดการ trashing หลายไฟล์ที่มีชื่อเดียวกันโดยไม่เขียนทับไฟล์ถังขยะเก่าและอนุญาตให้มีการเรียกคืนไฟล์ไปยังตำแหน่งเดิมของพวกเขาด้วยคำสั่งง่ายๆ (ชนิดของ“ยกเลิก”) ยิ่งไปกว่านั้นมันจะดีถ้าถังขยะถูกรีบูทโดยอัตโนมัติเมื่อรีบูท (หรือกลไกที่คล้ายกันเพื่อป้องกันการเติบโตไม่สิ้นสุด)

โซลูชันบางส่วนสำหรับสิ่งนี้มีอยู่จริง แต่การกระทำ“ คืนค่า” โดยเฉพาะนั้นไม่สำคัญ มีโซลูชันที่มีอยู่สำหรับสิ่งนี้ซึ่งไม่พึ่งพาระบบถังขยะจากเชลล์กราฟิกหรือไม่?

(นอกเหนือจากนี้มีการพูดคุยกันอย่างไม่รู้จบไม่ว่าจะเป็นวิธีการที่เป็นธรรมมากกว่าการใช้การสำรองข้อมูลบ่อยครั้งและ VCS ในขณะที่การสนทนาเหล่านั้นมีประเด็นผมเชื่อว่ายังคงมีช่องสำหรับคำขอของฉัน)


4
อาจเกี่ยวข้องกับคำถาม SuperUser สองคำสั่งเพื่อย้ายไฟล์ไปที่ถังขยะ ความแตกต่างคืออะไร? . ฉันเคยใช้gvfs-trashในอดีต แต่ไม่จำเป็นต้องกู้คืนจากบรรทัดคำสั่งจนกว่าคุณจะจุดประกายความอยากรู้ของฉัน คำตอบของคำถามที่เชื่อมโยงอาจช่วยได้
ephsmith

1
@ ช่างประปาขอบคุณลิงค์ดี ปัญหาเกี่ยวกับวิธีการเหล่านั้นแม้ว่าพวกเขาจะผูกพันกับ desktop shell เฉพาะ (อะไรคือคำที่ถูกต้องที่นี่?) การใช้งานบางสิ่งที่ฉันต้องการหลีกเลี่ยง
Konrad Rudolph

1
ย้ายไฟล์จากระบบไฟล์ใด ๆ ไปยัง ~ เจตนาของคุณหรือไม่ เพราะบางวันคุณอาจลบภาพ iso 4GB ที่อยู่บน dir ที่เมาท์ด้วย sshfs จากเซิร์ฟเวอร์ระยะไกลจริงๆ
Mischa Arefiev

1
@Mischa บอกตามตรงฉันไม่ได้คิดมากขนาดนั้น ที่กล่าวว่าควรทำงานกับสิทธิ์ของผู้ใช้ตามปกติดังนั้นเป้าหมายต้องเป็นตำแหน่งที่เขียนได้และไม่ควรใช้การกำหนดค่ามากเกินไป
Konrad Rudolph

3
ทำสิ่งที่คุณต้องการเช่นคำตอบที่ระบุไว้ในคำตอบด้านล่าง แต่อย่าตั้งชื่อมันว่า rm ตามที่คนอื่น ๆ ชี้ให้เห็นการเปลี่ยนชื่อ / เปลี่ยนคำสั่งมาตรฐานทำให้คุณเสี่ยงเมื่อคุณพยายามใช้คำสั่งเหล่านี้ในระบบอื่น แต่มันจะทำให้เกิดปัญหากับคนอื่น ๆ (อาจช่วยคุณ) โดยใช้ระบบ / บัญชีของคุณ
Joe

คำตอบ:


37

มีข้อกำหนด (ฉบับร่าง) สำหรับถังขยะบน freedesktop.org เห็นได้ชัดว่าสิ่งที่มักจะนำมาใช้โดยสภาพแวดล้อมเดสก์ทอป

การดำเนิน commandline จะเป็นถังขยะ CLI ดูเหมือนจะให้ความสนุกสนานที่คุณต้องการ ถ้าไม่บอกให้เราทราบว่านี่เป็นเพียงส่วนหนึ่งเท่านั้น

สำหรับการใช้โปรแกรมใด ๆ ที่เกี่ยวข้องกับการเปลี่ยน / นามแฝงrmนั้นมีเหตุผลที่ดีที่จะไม่ทำเช่นนั้น สิ่งสำคัญที่สุดสำหรับฉันคือ:

  • โปรแกรมจะต้องเข้าใจ / จัดการกับrmตัวเลือกทั้งหมดและดำเนินการตามนั้น
  • มันมีความเสี่ยงที่จะคุ้นเคยกับความหมายของ "rm ใหม่" ของคุณและดำเนินการคำสั่งที่มีผลร้ายแรงเมื่อทำงานกับระบบของผู้อื่น

นอกจากนี้ยังมีlibtrashซึ่งจะย้ายไฟล์ที่ถูกลบทั้งหมดไปยังถังขยะโดยอัตโนมัติผ่าน LD_PRELOAD (แต่ดูเหมือนว่าจะมีข้อบกพร่องหลายประการ) Autotrashช่วยทำความสะอาดถังขยะในวิธีที่ง่าย
jofel

ฉันสงสัยเกี่ยวกับสิ่งที่เป็นนิสัยของการใช้ RM ฉันอยู่ในนิสัยแล้วน่าเสียดาย
Konrad Rudolph

@jofel: libtrash มีแนวคิดที่ดีจริงๆ ชั้นลึกกว่าอีกสองสามชั้น มันน่าเสียดายที่มันเป็นรถ (และดูเหมือนจะไม่ใช้งานมาก)
zpea

4
@ KonradRudolph: ฉันหมายถึงว่าคนที่คุ้นเคยกับความจริงที่ว่า rm (อันที่ถูกแทนที่) ไม่ได้ลบอะไรจริงๆดังนั้นคนที่ระวังตัวน้อยลงก็เป็นไปได้ที่การกู้คืนจะเป็นไปได้เสมอ แน่นอนว่าการใช้ตัว rm นั้นไม่ใช่สิ่งเลวร้ายและไม่คุ้นเคยกับมัน
zpea

4
ฉันสิ้นสุดการใช้โซลูชันนี้และปิดใช้งานrmดังนั้นฉันจึงไม่สามารถใช้งานได้โดยไม่ตั้งใจ (ยังมี/bin/rmในกรณีที่ฉันต้องการจริงๆ)
Konrad Rudolph

9

Trash-cliเป็นแอพพลิเคชั่น linux ที่สามารถติดตั้งโดยใช้ apt-get ใน Ubuntu หรือ yum ใน Fedora การใช้คำสั่งtrash listOfFilesจะย้ายรายการที่ระบุไปยังถังขยะของคุณ


ในการสนับสนุนข้อเสนอแนะนี้: apple.stackexchange.com/a/17637/37190
Ioannis Filippidis

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'ในไฟล์นิยาม alias ของฉันแล้ว ttเป็นตัวช่วยจำสำหรับ 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ซึ่งทำสิ่งนี้

ดูเหมือนจะไม่ตอบสนองต่อ params เช่น-rหรือ-f(ดูเหมือนว่าเพิ่งย้ายไฟล์ / ไดเรกทอรีไปยังไดเรกทอรี ~ / .Trash) แต่จะไม่แทนที่ไฟล์ที่มีชื่อเดียวกัน (จะต่อท้าย "คัดลอก" ไปยัง ไฟล์ / ไดเรกทอรีที่มีชื่อเหมือนกัน)

เพื่อติดตั้งด้วยการชง

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การขึ้นบรรทัดใหม่และจะไม่หนีในไฟล์ metadata

2

เริ่มต้นด้วยการกำหนดmove_to_trashฟังก์ชั่น:

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

จากนั้นนามแฝงrmที่:

alias rm='move_to_trash'

คุณสามารถเรียกเก่าหนีด้วยเครื่องหมายเช่นนี้rm\rm

ฉันไม่ทราบวิธีการทำให้ไดเรกทอรีถังขยะว่างเปล่าเมื่อรีบูต (ขึ้นอยู่กับระบบของคุณคุณอาจต้องดูrc*สคริปต์) แต่มันก็คุ้มค่าที่จะสร้างcronงานที่ล้างไดเรกทอรีเป็นระยะ


2
น่าเสียดายที่นั่นเป็นส่วนที่ง่าย…: /
Konrad Rudolph

สคริปต์นี้ยังสามารถสร้างไฟล์ข้อความในไดเรกทอรีที่ซ่อนอยู่สำหรับแต่ละไฟล์ที่มีไดเรกทอรีเดิมสคริปต์คืนค่าสามารถอ่านตำแหน่งเดิมและย้ายกลับ
ephsmith

นอกจากนี้ยังมีอันตรายของไฟล์ที่ถูกลบหลายไฟล์ที่มีชื่อเดียวกันจะชนกันในไดเรกทอรีถังขยะและจะมีเพียงไฟล์เดียวที่ถูก "ลบ" ล่าสุดเพื่อให้สามารถกู้คืนได้
killermist

@ kermermist ใช่ แน่นอนว่าเราต้องทำอะไรเพิ่มเติมด้วยคำสั่ง move ตั้งชื่อไฟล์ "ถังขยะ" ตามที่คุณต้องการและคงเส้นทางเดิมไว้: | ทั้งหมดนี้กรีดร้องว่า "ทำไมต้องสร้างวงล้อใหม่" มีวิธีแก้ไขปัญหานี้อยู่แล้ว
ephsmith

นอกจากนี้ให้ใช้ชื่อนามแฝงอื่น ทำงานกับเครื่องอื่นโดยไม่ต้องใช้นามแฝงของคุณเพียงสายเดียวrmและไปยังไฟล์ของคุณ delอาจเป็นทางเลือกที่ดีกว่า
เกล็นแจ็คแมน

1

คุณสามารถใช้เดลของฉัน:

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

del ย้ายไฟล์ใน. del / ไดเร็กทอรีย่อย (และ back)

การใช้งาน: del [-v] [-u] ไฟล์
       del [-v] -p [-r] [-d days] [directory]
       del [-v] -l
ตัวเลือก: โหมด -v verbose
         -u ยกเลิกการลบไฟล์
         -p กำจัดไฟล์ที่ถูกลบ [เก่ากว่า -d วัน]
         -r ซ้ำ (ไดเรกทอรีย่อยทั้งหมด)
         รายการไฟล์ที่ถูกลบ
ตัวอย่าง: del * .tmp # ลบไฟล์ * .tmp ทั้งหมด
          del -u project.pl # ยกเลิกการลบ project.pl
          del -vprd 2 # verbose purge ลบไฟล์ที่เก่ากว่า 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.