Bazıları dışındaki tüm dosyaları bir dizinden kaldır


215

Kullanırken sudo rm -raşağıdakiler hariç tüm dosyaları nasıl silebilirim:

textfile.txt
backup.tar.gz
script.php
database.sql
info.txt


1
Orada bu soruyu okumak için 2 yol vardır ve var olan cevaplar her iki yorumları kapsamaktadır: YA: (a) Belirtilen adlarla dosyaları korumak doğrudan hedef dizinde ve bulunduğu - olarak rm -rima - alt dizinleri dahil olmak başka silme şeyi, - içerdikleri bile belirtilen adlara sahip dosyalar; VEYA: (b) hedef dizinin tüm alt ağacında gezinin ve her dizinde, listelenen adların dışındaki tüm dosyaları silin.
mklement0

Yanıtlar:


219
find [path] -type f -not -name 'textfile.txt' -not -name 'backup.tar.gz' -delete

Find belirtmezseniz -type f, istemeyebileceğiniz dizinleri de listeler.


Veya çok kullanışlı kombinasyonu kullanan daha genel bir çözüm find | xargs:

find [path] -type f -not -name 'EXPR' -print0 | xargs -0 rm --

örneğin, geçerli dizindeki txt olmayan tüm dosyaları silin:

find . -type f -not -name '*txt' -print0 | xargs -0 rm --

print0Ve -0silinmelidir dosya adlarına herhangi birinde boşluk varsa kombinasyonu gereklidir.



26
birden fazla desen silmek için:find . -type f -not -name '*ignore1' -not -name '*ignore2' | xargs rm
Siwei Shen 申思维

5
dizinler ne olacak? tüm dosyaları siler, ancak klasörleri kaldırır mı ?!
2013

31
"| Xargs rm" yerine find, bir -delete parametresi alır.
Emil Stenström

1
yerine -print0 | xargs -0 rm --sadece-delete
Andy

151
rm !(textfile.txt|backup.tar.gz|script.php|database.sql|info.txt)

Extglob'un (Genişletilmiş Desen Eşleme) BASH'de etkinleştirilmesi gerekir (etkin değilse):

shopt -s extglob

2
Yaptığım zaman "sözdizimi hatası beklenmedik belirtecinin yakınında (" "alıyorum shopt -s extglob; rm -rf !(README|LICENSE). Neden
Dennis

@nic Hatırlamıyorum üzgünüm. Muhtemelen kullanarak sona erdi findile -deleteseçeneği.
Dennis

Bu benim için en iyi çözüm ve varsayılan olarak Ubuntu 12.04.4 LTS'de shopt'a gerek duymadan çalışıyor
xtian

3
@nic, @Dennis: Sözdizimi hatası, DIĞER bir şeyin bashkullanıldığını, örneğin desteklenmeyen dashyerlerde extglobolduğunu gösterir. Ancak, etkileşimli bir bash kabukta, komut AYRICA farklı nedenlerle belirtildiği gibi çalışmaz. Kısaca: ITSELF shopt -s extglobİLE yürüt ; ONCE BAŞARIYLA ETKİNLEŞTİRİLDİ (ile doğrulayın shopt extglob), yürütün rm -rf !(README|LICENSE). ( extglobHenüz etkin olmasa da , komutlar yürütülmeden ÖNCE geçmiş genişlemesi!(...) tarafından değerlendirilir ; bu büyük olasılıkla başarısız olduğundan, NEITHER komutu yürütülür ve asla açık olmaz.)extglob
mklement0 3

2
@nic, @Dennis, @ mklement0: Bir .sh dosyası (#! / bin / bash) içinde komut çalıştırırken "# beklenmedik belirtecin yanında sözdizimi hatası" ile aynı sorunu yaşadım, ancak bir komutta çalıştırdığımda değil . satırı arayüzü o ek olarak ortaya çıktı shopt -s extglobkomut satırı arayüzünde vadede, benim komut dosyası içine yeniden gerekiyordu bu benim için sorun çözüldü..
Ahresse

41

find . | grep -v "excluded files criteria" | xargs rm

Bu, geçerli dizindeki tüm dosyaları listeler, ardından ölçütlerinize uymayan tüm dosyaları listeler (dizin adlarıyla eşleşenlere dikkat edin) ve sonra bunları kaldırın.

Güncelleme : düzenlemenize bağlı olarak, listelediğiniz dosyalar dışında mevcut dizindeki her şeyi gerçekten silmek istiyorsanız, bu kullanılabilir:

mkdir /tmp_backup && mv textfile.txt backup.tar.gz script.php database.sql info.txt /tmp_backup/ && rm -r && mv /tmp_backup/* . && rmdir /tmp_backup

Bir yedekleme dizini oluşturacaktır /tmp_backup(kök ayrıcalıklarınız var, değil mi?), Listelediğiniz dosyaları bu dizine taşıyın, geçerli dizindeki her şeyi tekrarlayın (doğru dizinde olduğunuzu biliyorsunuz, değil mi?), Taşıyın geçerli dizine geri dönün /tmp_backupve son olarak silin /tmp_backup.

Kökte olmak için yedekleme dizinini seçiyorum, çünkü her şeyi kökten yinelemeli olarak silmeye çalışıyorsanız, sisteminizde büyük sorunlar olacaktır.

Elbette bunu yapmanın daha zarif yolları var, ama bu oldukça basit.


2
Ayrıca egrep ile gerçekten iyi çalışır, örneğin ara lateks dosyalarını temizlemek için:find . | egrep -v "\.tex|\.bib" | xargs rm
mtsz

inanılmaz komut! dizinleri kaldırmak için sadece rm -r olarak değiştirin
Aris

1
Geçerli dizindeki hariç tutulan ölçütler dışındaki her şeyi silmek istiyorsanız: find . -maxdepth 1 | grep -v "exclude these" | xargs rm -rgereksiz yere dizinlere gitmesi gerekmediğinden çok daha hızlı çalışır.
billynoah

Yeniden findboru hattı oluşturma: verimlilik sorunları bir yana ( findtek başına yapılabilecekler için 3 komut kullanılır ), bu, gömülü boşluklara sahip dosya adlarıyla amaçlandığı gibi çalışmaz ve muhtemelen yanlış dosyaları siler.
mklement0

"Kaydedilecek" dosyaları başka bir konumda ( /tmp_backup) saklayan bir komut, kesintiye uğrarsa iyi bitmez - kullanıcının bakış açısından, onları geri almak için nereye bakacaklarını bilmedikleri sürece tüm dosyalar yok olmuştur. . Bu nedenle bu tür bir stratejiden yanayım.
Craig McQueen

20

Bu adlara sahip dosyaların dizin ağacında birden çok yerde bulunduğunu ve tümünü korumak istediğinizi varsayarsak:

find . -type f ! -regex ".*/\(textfile.txt\|backup.tar.gz\|script.php\|database.sql\|info.txt\)" -delete

19

Bash'te GLOBIGNORE ortam değişkenini kullanabilirsiniz.

Php ve sql dışındaki tüm dosyaları silmek istediğinizi varsayalım, o zaman aşağıdakileri yapabilirsiniz -

export GLOBIGNORE=*.php:*.sql
rm *
export GLOBIGNORE=

GLOBIGNORE'un bu şekilde ayarlanması, "ls *" veya "rm *" gibi kullanılan joker karakterlerden php ve sql'i yok sayar. Bu nedenle, değişkeni ayarladıktan sonra "rm *" kullanıldığında yalnızca txt ve tar.gz dosyası silinir.


6
+ 1; GLOBIGNOREDeğişkeni ayarlamak ve geri yüklemek için daha basit bir alternatif, bir alt kabuk kullanmaktır:(GLOBIGNORE='*.php:*.sql'; rm *)
mklement0

19

Alt sorgu listesini kullanmayı tercih ediyorum:

rm -r `ls | grep -v "textfile.txt\|backup.tar.gz\|script.php\|database.sql\|info.txt"`

-v, --invert-match eşleşen olmayan satırları seç

\| Ayırıcı


1
Zarif çözüm
Joshua Salazar

9

Kimse bundan bahsetmediği için:

  • silmek istemediğiniz dosyaları güvenli bir yere kopyalayın
  • tüm dosyaları sil
  • kopyalanan dosyaları yerine geri taşı

2
Bu daha karmaşıktır, çünkü izinleri geri kopyaladıktan sonra ilgilenmeniz gerekir.
Romulus

2
@RemusAvram İzinleri korumak için cpveya ile uygun anahtarları kullanabilirsiniz rsync. Her neyse, bu sadece OP'nin cevabı olarak burada yerini alan alternatif bir yöntemdir (öneri olarak verilir).
gniourf_gniourf

Bu, saklanacak dosyaların diğer işlemler tarafından aktif olarak kullanıldığı birçok durumda uygun olmayabilir. Ayrıca kaldırılacak dosyaların hantal sadece küçük bir alt küme ve çok sayıda dosya yer alıyor.
codeforester

@codeforester: tabi. Ama bunun uygun olduğu durumlar da var ... aslında yorumunuzun amacını gerçekten göremiyorum :).
gniourf_gniourf

6

Bunun için bir for döngüsü yazabilirsiniz ...%)

for x in *
do
        if [ "$x" != "exclude_criteria" ]
        then
                rm -f $x;
        fi
done;

6

OP için biraz geç, ama umarım daha sonra google tarafından buraya gelen herkes için yararlıdır ...

@Awi'nin cevabını buldum ve @Jamie Bullock tarafından -delete yorum gerçekten yararlı. Basit bir yardımcı program, bunu farklı dizinlerde her seferinde en az yazarak farklı dosya adlarını / türlerini yok sayarak yapabilirsiniz:

rm_except (ya da adlandırmak istediğiniz her şeyi)

#!/bin/bash

ignore=""

for fignore in "$@"; do
  ignore=${ignore}"-not -name ${fignore} "
done

find . -type f $ignore -delete

örneğin metin dosyaları ve foo.bar dışındaki her şeyi silmek için:

rm_except *.txt foo.bar 

Mishunika'ya benzer, ancak if cümlesi olmadan.


5

Eğer kullanıyorsanız zshson derece tavsiye ederim.

rm -rf ^file/folder pattern to avoid

İle extended_glob

setopt extended_glob
rm -- ^*.txt
rm -- ^*.(sql|txt)

4

Bunu denemek çalıştı:

rm -r !(Applications|"Virtualbox VMs"|Downloads|Documents|Desktop|Public)

ancak boşluklu isimler (her zamanki gibi) zordur. Virtualbox\ VMsBunun yerine tırnak işaretleri ile de denedim . Her zaman o dizini ( Virtualbox VMs) siler .


Dosyalar için ÇALIŞMAZ. rm !(myfile.txt)dahil olmak üzere tüm kaldırırmyfile.txt
khaverim

shopt -s extglob@ pl1nk dikkat çekti olarak ilk yürütmek gerekir
zhuguowei

Evet, genişletilmiş globbing'i ( extglob ) bash'da etkinleştirmek çok önemlidir, bunu günlük rutin olarak, laboratuarlarda birkaç Mac üzerinden yapıyorum: shopt -s extglobve sonra cd /Users/alumno/ve sonunda buradarm -rf !(Applications|Virtualbox*VMs|Downloads|Documents|Desktop|Public|Library) genişletilmiş globbing hakkında okuyun
juanfal

4

Sadece:

rm $(ls -I "*.txt" ) #Deletes file type except *.txt

Veya:

rm $(ls -I "*.txt" -I "*.pdf" ) #Deletes file types except *.txt & *.pdf

Bu önerilmez. Ayrıştırma lsçıktısı sorun haline gelebilir. Ayrıntılı bilgi için Buraya bakınız .
RJ

2

Dosyaları değiştirilemez hale getirin. Köklerin bile silmesine izin verilmez.

chattr +i textfile.txt backup.tar.gz script.php database.sql info.txt
rm *

Diğer tüm dosyalar silindi.
Sonunda bunları değiştirilebilir.

chattr -i *

0

Bu @ siwei-shen'deki yoruma benzer, ancak -obirden çok desen yapmak için bayrağa ihtiyacınız var . -oBayrak 'veya' açılımı

find . -type f -not -name '*ignore1' -o -not -name '*ignore2' | xargs rm


0

Bunu iki komut dizisiyle yapabilirsiniz. İlk olarak, hariç tutmak istemediğiniz dosyaların adıyla bir dizi tanımlayın:

files=( backup.tar.gz script.php database.sql info.txt )

Bundan sonra, dosya adının hariç tutmak istemediğiniz dizide olup olmadığını kontrol ederek dizinde hariç tutmak istediğiniz tüm dosyalar arasında gezinin; değilse, dosyayı silin.

for file in *; do
  if [[ ! " ${files[@]} " ~= "$file"  ]];then
    rm "$file"
  fi
done

Normal ifade karşılaştırması yanlıştır - adı korunan dosyalardan birinin alt dizesi olan herhangi bir dosyayı korur (ancak çevresindeki boşluklar bunu hafifletir; ancak dosya adları boşluk içerebilir). Tüm dosyaların bir dizisini toplamalı, ardından bu diziden hariç tutmak istediğiniz dosyaları çıkarmalı ve ardından kalan dosyaları kaldırmalısınız.
Üçlü

-1

Henüz kimse bundan bahsetmediği için, belirli bir durumda:

OLD_FILES=`echo *`
... create new files ...
rm -r $OLD_FILES

(veya sadece rm $OLD_FILES)

veya

OLD_FILES=`ls *`
... create new files ...
rm -r $OLD_FILES

shopt -s nullglobBazı dosyalar orada olsa da olmasa da kullanmanız gerekebilir:

SET_OLD_NULLGLOB=`shopt -p nullglob`
shopt -s nullglob
FILES=`echo *.sh *.bash`
$SET_OLD_NULLGLOB

nullglob olmadan, echo *.sh *.bashsize "a.sh b.sh * .bash" verebilir.

(Tüm bunları söyledikten sonra , OSX'de çalışmıyor olsa bile kendim bu cevabı tercih ediyorum )


Leonardo Hermoso'nun mevcut cevabı bunu daha az hata ile yapıyor. Bu, boşluklu dosya adları için başarısız olur; bir dizi kullanmak bu problemi zarif bir şekilde çözer (ve aynı zamanda özel değişkenleri için büyük harf kullanmaktan daha az kaçınılmazdır, bu genellikle kaçınılmalıdır).
Üçlü

-3

Doğrudan bir komut almak yerine, lütfen gerekli dosyaları geçici dir komutunun geçerli dizin dışına taşıyın. Ardından rm *veya tuşlarını kullanarak tüm dosyaları silin rm -r *.

Sonra gerekli dosyaları geçerli dizine taşıyın.


Bu, saklanacak dosyaların diğer işlemler tarafından aktif olarak kullanıldığı birçok durumda uygun olmayabilir. Ayrıca kaldırılacak dosyaların hantal sadece küçük bir alt küme ve çok sayıda dosya yer alıyor.
codeforester

-3

File.name hariç her şeyi kaldırın:

ls -d /path/to/your/files/* |grep -v file.name|xargs rm -rf

2
Bu korkunç bir şekilde başarısız olur ve dizininiz / dosyalarınızda boşluklar veya olağandışı karakterler varsa veri kaybına neden olabilir. Asla ayrıştırmamalısınız. mywiki.wooledge.org/ParsingLs
RJ
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.