'Rm -rf' den korunan bir dizin oluşturma


9

Sadece yaptıktan sonra B klasöründe olan A klasöründeki bazı verileri kaybettim rm -rf B. Ne yaptığımı fark etmeden önce her şey bitmişti. Şimdi bir ders öğrenildi, bir dahaki sefere benzer bir şey yaptığımda ve kendimi öldürmek istediğimde klasörümün bir kısmını aptal geçirmez yapmak istiyorum.

Düşünebileceğim bir yol, bir bash işlevi yazmak ve bunu diğer adı yapmaktır rm. Bu işlev, her bir alt klasöre gibi gizli bir dosya arar .dontdelete. Bulduğumda, gerçekten devam etmek isteyip istemediğimi sorardı. Yapamam yazma korumalı çünkü bu klasöre sürekli yazılan bir işlem var. Bunu yapmanın daha iyi bir yolu var mı?


2
Eğer takma çalıştı mı rmhiç rm -i:> -i istemi önce her kaldırma veya> -I üçten fazla dosyaları kaldırarak veya yinelemeli çıkartırken önce bir kez istemi. Çoğu hataya karşı koruma sağlarken -i'den daha az müdahaleci olabilir. Başka bayraklara sahip olanları istediğiniz zaman yazabilirsiniz.
IBr

2
Çıkışsafe-rm
sr_

Bunu yapmanın yaklaşık bir düzine yolu var. Ortamınızla ilgili daha fazla ayrıntıya girmeniz gerekecek.
Ignacio Vazquez-Abrams


Başka bir fikir, onu sadece belirli bir klasöre taşıyan bir işleve takmak ve daha sonra tmpwatchher saatte bu klasörden dosyaları silmek için çalışan bir cronjob oluşturmaktır .
Bratchley

Yanıtlar:


14

Sorunuzu araştırırken gelecekte size yardımcı olabilecek bu teknikle karşılaştım.

Görünüşe göre dizindeki bir dosyaya şu şekilde dokunabilirsiniz:

touch -- -i

Şimdi komutu mevcut rm -fr *olan bir dizinde çalıştırdığınızda, -isize interaktif bilgi istemi sunulur rm.

$ ls
file1  file2  file3  file4  file5  -i

$ rm -fr *
rm: remove regular empty file `file1'? n
rm: remove regular empty file `file2'? n
rm: remove regular empty file `file3'? n
rm: remove regular empty file `file4'? n
rm: remove regular empty file `file5'? n

Aynı şey, rmher zaman yapmak için bir takma adı yerinde bırakarak da elde edilebilir rm -i. Bu can sıkıcı olabilir. Sık sık yaptığım şey, bu takma adı yerine koymak ve gerçekten sorulmadan silmek istediğinizde devre dışı bırakmaktır.

alias rm='rm -i'

Şimdi dizinlerde şöyle karşılanacaksınız:

$ ls
file1  file2  file3  file4  file5

$ rm -r *
rm: remove regular empty file `file1'?

Takma adı geçersiz kılmak için:

$ \rm -r *

rm -frAncak bu yine de durmuyor . Ancak size biraz koruma sağlar.

Referanslar


1
Bu, sadece küçük bir dizin kümesini korumak / korumak istiyorsanız iyi çalışan güzel ve zarif bir çözümdür. Ve ben eski kafalı olabilirim ama yine --forcede bir şeye söylersen gerçekten kastettiğin izlenimi altında yaşıyorum .
CVn

Ayrıca rm -I(büyük harf i) bir takma adda yararlı olabilir, çünkü biraz daha az müdahaleci (man sayfasına göre, sadece üçten fazla dosyayı kaldırırsanız veya özyinelemeli olarak sorulur).
CVn

Not o touch ./-ihile, sadece GNU ile çalışır rmve sadece POSIXLY_CORRECT değişken (POSIX komutlar argümanları sonra seçenekleri tanımaz) ayarlı değilse.
Stéphane Chazelas

5

Birçok olasılık:

  • alias rm='rm -i'- rm soracaktır - siz belirtmedikçe -f...
  • chmod -w dir - dosyaları doğrudan bu dizinde korur.
  • chattr +i gerçekten demek istiyorsan
  • rm etrafına kendi ambalajını yaz
  • vb...

Ancak daha iyi bir yol, muhtemelen iyi bir yedeğe sahip olmak ve önemli verileri bir çeşit sürüm kontrolünde tutmaktır (örneğin git), bu da başka birçok avantaj getirir.


1
Bundan bahsetmek için buraya geldim. Tamamen güvenli hale getirmek için chattr + i'yi öneririm.
JZeolla

Zaten rm takma var rm -iama bir beklendiği gibi, -fseçeneği ile çalışmıyor . Git'i başka birçok amaçla kullanıyorum, ama yanlışlıkla rm -rf *git'te de yaparsam ne olur ?
Dilawar

Git ile, yalnızca bir alt dizini kaldırırsanız, yerel deponuzdan kolayca geri yükleyebilirsiniz. Deponun tamamını kaldırırsanız, daha önce başka bir yere ittiğinizde, onu tekrar klonlayabilirsiniz.
michas

1

gitProjelerinizi kapsüllemek gibi bir sürüm kontrol yazılımı kullanın .

Tüm bir projeyi silmediğiniz sürece rm -rf .*, .gitdizini kaldırmak ve geri alma için gereken tüm verileri kaybetmek için kasıtlı olarak yazmanız gerekir .

Bu, eşyalarınızın yedeklemelerini github veya bitbucket gibi uzak bir sunucuya gönderebileceğiniz ek bir avantaja sahiptir.


1

Nasıl rm -rf dirçalışır:

  1. Açılır dirve içeriğini listeler.
  2. Her giriş için, eğer bir dizinse, aynı işlemi tekrarlayın, eğer değilse, çağırın unlink.

Dizin listeleme için önce özel bir dosya adı döndürdüyseniz ve unlinkbu dosya üzerinde bir işlem yaparak ölüme neden olabilirseniz , bu sorunu çözecektir. Bu bir sigorta dosya sistemi kullanılarak yapılabilir.

Örneğin, adapte olabilir loopback.plörnek gelen perl Fuse modülü şöyle bir gerçek dosya sistemi ve alt kısımda geçiyorsa geçiş sadece sadece bir kukla dosya sistemini uygulayan (ayrıca aşağıda yama bakın):

  • bir dizini listelerken, adında bir girdi içeriyorsa .{{do-not-delete}}., iki dosya içeren girdilerin başına ekleyin: .{{do-not-delete}}!errorve.{{do-not-delete}}!kill
  • unlinkbirincisine çalışırken , bir hata mesajı görüntüleyecek şekilde EPERMkodu rmdöndürün
  • unlinkikincisine çalışırken , süreç öldürülür.

$ ls -Ff dir/test
./  .{{do-not-delete}}.  foo/  ../  bar
$ ./rm-rf-killer dir
$ ls -Ff dir/test
.{{do-not-delete}}!error  .{{do-not-delete}}!kill  ./  .{{do-not-delete}}.   foo/  ../  bar
$ rm -rf dir/test
rm: cannot remove `dir/test/.{{do-not-delete}}!error': Operation not permitted
zsh: terminated  rm -rf dir/test
$ ls -Ff dir/test
.{{do-not-delete}}!error  .{{do-not-delete}}!kill  ./  .{{do-not-delete}}.   foo/  ../  bar

İşte bir kavram kanıtı olarak bu loopback.plörneğin üstüne uygulanacak bir yama :

--- loopback.pl 2013-06-03 22:35:00.577316063 +0100
+++ rm-rf-killer    2013-06-03 22:33:41.523328427 +0100
@@ -7,2 +7,4 @@
 my $has_threads = 0;
+my $flag = ".{{do-not-delete}}";
+
 eval {
@@ -42,3 +44,4 @@

-use blib;
+#use blib;
+use File::Basename;
 use Fuse;
@@ -49,3 +52,3 @@

-my %extraopts = ( 'threaded' => 0, 'debug' => 0 );
+my %extraopts = ( 'threaded' => 0, 'debug' => 0, 'mountopts' => 'nonempty' );
 my($use_real_statfs, $pidfile);
@@ -64,3 +67,7 @@

-sub fixup { return "/tmp/fusetest-" . $ENV{LOGNAME} . shift }
+sub fixup {
+    my $f = shift;
+    $f =~ s#(/\Q$flag\E)!(error|kill)$#$1.#s;
+    return ".$f";
+}

@@ -78,3 +85,9 @@
 }
-    my (@files) = readdir(DIRHANDLE);
+    my @files;
+    
+    while (my $f = readdir(DIRHANDLE)) {
+        unshift @files, "$flag!error", "$flag!kill"
+            if ($f eq "$flag.");
+        push @files, $f;
+    }
 closedir(DIRHANDLE);
@@ -121,3 +134,12 @@
 sub x_readlink { return readlink(fixup(shift));         }
-sub x_unlink   { return unlink(fixup(shift)) ? 0 : -$!; }
+sub x_unlink   {
+    my $f = shift;
+    if (basename($f) eq "$flag!error") {return -EPERM()}
+    if (basename($f) eq "$flag!kill") {
+        my $caller_pid = Fuse::fuse_get_context()->{"pid"};
+        kill("TERM", $caller_pid);
+        return -EPERM();
+    }
+    return unlink(".$f") ? 0 : -$!;
+}

@@ -203,3 +225,2 @@
 sub daemonize {
-    chdir("/") || die "can't chdir to /: $!";
 open(STDIN, "< /dev/null") || die "can't read /dev/null: $!";
@@ -236,2 +257,3 @@

+chdir($mountpoint) or die("chdir: $!");
 daemonize();
@@ -239,3 +261,3 @@
 Fuse::main(
-    'mountpoint'    => $mountpoint,
+    'mountpoint'    => '.',
 'getattr'       => 'main::x_getattr',

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.