Rm 'nin çöp kutusuna taşınmasını sağlayın


54

Dosyaları silmek yerine, onları özel bir "çöp kutusu" konumuna getiren bir Linux komut dosyası / uygulaması var mı? Bunun yerine geçmesini isterim rm(belki ikincisini takma bile kullanabilirsiniz; bunun için artılar ve eksiler vardır).

“Çöp” derken özel bir klasör kastediyorum. Tek mv $* ~/.trashadım bir ilk adımdır, ancak ideal olarak bu daha eski şifreli dosyaların üzerine yazmadan aynı addaki birkaç dosyayı silmekle başa çıkmalı ve dosyaları basit bir komutla (bir tür “geri al”) geri yükleyebilmelidir . Ayrıca, çöpün otomatik olarak yeniden başlatılmasından (veya sonsuz büyümeyi önlemek için benzer bir mekanizmaya) boşaltılması iyi olurdu.

Bunun için kısmi çözümler var, ancak özellikle “geri yükleme” işlemi önemsiz değil. Bunun için bir grafik kabuğundan gelen bir çöp sistemine dayanmayan mevcut çözümler var mı?

(Bir kenara, sık sık yedeklemeler ve VCS kullanmak yerine bu yaklaşımın haklı olup olmadığı konusunda hiç durmadan tartışmalar oldu.


4
Bu, Süper Kullanıcı sorusuyla ilişkili olabilir Dosyaları çöp kutusuna taşımak için iki komut. Fark ne? . gvfs-trashGeçmişte kullandım , ancak merakımı uyandırıncaya kadar komut satırından geri yükleme yapma gereksinimim olmadı. Bağlantılı sorunun cevabı yardımcı olabilir.
ephsmith

1
@ephsmith Teşekkürler, iyi bağlantı. Bu yaklaşımlarla ilgili sorun, kaçınmak istediğim bir şey olan belirli masaüstü kabuğuna (buradaki doğru terim nedir?) Uygulamalarına bağlı olmalarıdır.
Konrad Rudolph

1
Dosyaları herhangi bir dosya sisteminden kasıtlıya mı taşıyorsunuz? Çünkü bir gün sshfs ile monte edilmiş bir dir üzerinde bulunan 4GB iso görüntüsünü gerçekten uzak bir sunucudan siliyor olabilirsiniz.
Mischa Arefiev

1
@Mischa Dürüst olmak gerekirse, bu kadar düşünmedim. Bununla birlikte, normal kullanıcı hakları ile çalışması gerektiği için hedefin yazılabilir ve çok fazla yapılandırma gerektirmeyen bir yer olması gerekiyor.
Konrad Rudolph

3
Aşağıdaki cevaplarda belirtilen çözümler gibi ne istersen yap , ama ismini söyleme . Başkalarının da belirttiği gibi, standart komutları yeniden adlandırmak / yeniden düzenlemek, alışılmış şekilde diğer sistemlerde kullanmaya çalıştığınızda sizi savunmasız bırakır, ancak beklenmeyen sonuçlar ortaya çıktığında, sisteminizi / hesabınızı kullanarak başkaları (belki de size yardımcı olabilir) sorunlarına neden olur.
Joe,

Yanıtlar:


37

Freedesktop.org sitesinde Trash için bir özellik (taslak) var . Görünüşe göre genellikle masaüstü ortamları tarafından uygulanan şeydir.

Bir komut satırı uygulaması trash-cli olacaktır . Daha yakından bakmadan, istediğiniz işlevselliği sağlıyor gibi görünüyor. Değilse, bunun yalnızca kısmi bir çözüm olduğunu bize bildirin.

Herhangi bir programı değiştirme / takma ad olarak kullanmak rmsöz konusu olduğunda, bunu yapmamak için iyi nedenler var. Benim için en önemlisi:

  • Programın tüm rmseçenekleri anlaması / ele alması ve buna göre davranması gerekir.
  • Diğer insanların sistemleri üzerinde çalışırken "yeni rm" nin anlamına alışma ve ölümcül sonuçlara yol açan komutları kullanma riski vardır.

Ayrıca, silinen tüm dosyaları LD_PRELOAD üzerinden otomatik olarak çöp kutusuna taşıyan libtrash de vardır (ancak birkaç hataya sahip görünüyor). Otomatik çöp, çöpü kolayca temizlemenize yardımcı olur.
jofel

Kullanım alışkanlıklarından yararlanma yöntemini merak ediyorum. Ben zaten alışkanlıktayım, ne yazık ki.
Konrad Rudolph

@ jofel: libtrash'in gerçekten hoş bir konsepti var. Diğer yaklaşımlardan daha derin birkaç kat. Yazık buggy (ve çok aktif görünmüyor).
zpea

4
@KonradRudolph: Birinin rm'nin (değiştirilen) bir şeyi gerçekten silmemesi gerçeğine alışması, yani geri yükleme her zaman mümkün olduğu için birinin daha az dikkatli olması gerektiği anlamına geliyordu. Tabii ki, rm'nin kendisini kullanmak kötü bir şey değil, buna alışmak da değil.
zpea

4
Bu çözümü rmkullanmaya başladım ve devre dışı bıraktım, böylece yanlışlıkla kullanamıyorum ( /bin/rmgerçekten ihtiyacım olması durumunda hala var).
Konrad Rudolph


7

Önceki cevaplar komutlardan trash-clive rmtrash. Bunların hiçbiri varsayılan olarak Ubuntu 18.04'te bulunmaz, ancak komuttur gio. Komut gio help trashçıkışları:

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 FILENAMEKomut satırını kullanarak test ettim ve tıpkı dosyayı dosya tarayıcısında seçtiğim ve DEL düğmesini tıkladığım gibi çalışıyor: dosya masaüstünün Çöp klasörüne taşınır. (Bu -fseçeneği kullanmasam da, komut onay istemiyor .)

Yeniden tanımlanması daha uygun olsa dosyaların silinmesi bu şekilde ters yönde de rmolması rm -igüvenlik için ve yanlışlıkla yapmamalıydın bir silmeyi onaylamak eğer hala şans bırakır her silinmesini onaylamak zorunda.

Diğer alias tt='gio trash'ad tanımları dosyama ekledim ; ttTo Trash için bir anımsatıcıdır.

2018-06-27 tarihinde düzenlemeye eklendi: Sunucu makinelerinde, bir çöp dizini için eşdeğer yoktur. İşi yapan aşağıdaki Bash komut dosyasını yazdım; masaüstü makinelerde kullanır gio trashve diğer makinelerde, parametre (ler) olarak verilen dosyaları oluşturduğu çöp dizinine taşır. Script 2019-09-05 tarihinde güncellenmiştir.

#!/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

Bunu yapan rmtrash adında küçük bir yardımcı program var .

-rVeya gibi -fparagraflara cevap vermiyor gibi gözüküyor (aslında sadece dosyayı / dizini ~ / .Trash dizinine taşıyor gibi), ancak aynı adı taşıyan dosyaları geçersiz kılmaz ("Kopyala" ekler) benzeri adlandırılmış dosyalar / dizinler).

Demlemek ile yüklemek için

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

github.com/nateshmbhat/rm-trash . "rm-trash", çift dosya adlarını ve özyinelemeli silmeleri de yapar. Bunu kontrol et.
Natesh,

4

İşte ad çakışmasıyla başa çıkabilen ve aynı yol üzerinde saniyede birden fazla dosya silmediğiniz sürece birden çok silinmiş dosyaya izin veren hızlı ve kirli bir çöp sistemi.

Uyarı: Bu kodu doğrudan tarayıcımda yazdım. Muhtemelen kırılmış. Üretim verilerinde kullanmayın.

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
)

Bilinen Sorunlar:

  • Aynı dosyayı aynı anda birkaç kez silmeyi denerseniz zarafetle baş edemez.
  • Çöp dizini çok büyük olabilir, dosyalar karma değerin ilk birkaç basamağını temel alarak alt dizinlere gönderilmelidir.
  • trashdosya adlarındaki yeni satırlarla başa çıkmalı, ancak untrashdayandığından grepve yeni satırların meta veri dosyasından çıkmadığından kaynaklanmamalıdır.

2

Bir move_to_trashfonksiyon tanımlayarak başlayın :

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

Sonra buna takma rm:

alias rm='move_to_trash'

Hep eski çağırabilir rmböyle bir ters eğik çizgi ile kaçan tarafından: \rm.

Çöp dizinini yeniden başlatırken nasıl boş bırakacağımı bilmiyorum (sisteminize bağlı olarak, rc*komut dosyalarına bakmanız gerekebilir ), ancak crondizini düzenli aralıklarla boşaltan bir görev oluşturmakta fayda olabilir.


2
Maalesef, bu kolay kısmıydı…: /
Konrad Rudolph

Bu komut dosyası, içinde bulunduğu dizini içeren her dosya için gizli bir dizinde bir metin dosyası da oluşturabilir. Geri yükleme komut dosyası eski konumu okuyabilir ve geri taşıyabilir.
ephsmith

Bu aynı zamanda birden çok silinmiş dosyanın aynı isimde çöp dizininde çarpışması tehlikesi vardır ve yalnızca "silinen son dosya" kurtarılabilir durumda kalır.
killermist

@killermist, evet. Elbette, bir hareket komutu ile ek bir şey yapmak gerekir. İstediğiniz şekilde "çöpe atılan" dosyayı adlandırın ve orijinal yolu saklayın: | Tüm bunlar "neden tekerleği yeniden yarattığınızı" haykırıyor. Bu sorunun çözümü var.
ephsmith

Ayrıca, farklı bir takma ad kullanın. Takma adlarınız olmadan başka bir makinede çalışın, bir çağrı yapın rmve dosyalarınıza gidin. deldaha iyi bir seçim olabilir.
glenn jackman

1

Benim del kullanabilirsiniz:

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

del, dosyaları bir .del / alt dizininde (ve geri) taşır

kullanım: del [-v] [-u] dosya
       del [-v] -p [-r] [-d gün] [dizin]
       del [-v] -l
Seçenekler: -v ayrıntılı modu
         -u dosyaları sil
         -p silinmiş dosyaları temizleme [-d günden eski]
         -r özyinelemeli (tüm alt dizinler)
         -L silinen dosyaları listeler.
örnekler: del * .tmp # tüm * .tmp dosyalarını sil
          del -u project.pl # undelete project.pl
          del -vprd 2 # verbose 2 günden eski silinmiş dosyaları temizle

0

KDE 4.14.8'de, dosyaları çöp kutusuna taşımak için aşağıdaki komutu kullandım (Dolphin'de kaldırılmış gibi):

kioclient move path_to_file_or_directory_to_be_removed trash:/

Ek I: ile komut hakkında buldum

    ktrash --help
...
    Note: to move files to the trash, do not use ktrash, but "kioclient move 'url' trash:/"

Ek II: işlev (daha sonra .bashrc'nize bağlayın)

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
}
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.