Bir dosya dışındaki tüm dosyaları / dizinleri kaldır


244

Çok sayıda dosya içeren bir dizin var. File.txt dışındaki tüm dosyaları silmek istiyorum. Bunu nasıl yaparım?

İstenmeyenleri tek tek kaldırmak için çok fazla dosya var ve adları bu dosya dışındaki hepsini kaldırmak için * kullanmak için çok çeşitli.

Birisi kullanarak önerdi

rm !(file.txt)

Fakat işe yaramıyor. O döner:

Badly placed ()'s 

İşletim sistemim Scientific Linux 6'dır.

Herhangi bir fikir?


13
saklamak istediğinizi hareket ettirin, sonra diğerleri?
Olivier Dulac

5
@ OliverDulac Bu soruda, soruyu fazla düşünmeyen tek kişi biz miyiz?
Shadur

1
@shadur: peki, onlarla ilişki kurabilirim: oneliners çekici ... ^^
Olivier Dulac

1
Teşekkürler ve evet tek satırlık bir çözüm arıyordum. Bunu sık sık yapmak zorunda kaldığım için dosyaları dolaştırmak çok zaman alıyor.
Kantura

Yanıtlar:


288

POSIXly:

find . ! -name 'file.txt' -type f -exec rm -f {} +

dışında tüm düzenli dosyaları (nihayetinde gizli olanlar dahil) kaldırır file.txt. Dizinleri kaldırmak için, değiştirmek -type fiçin -type dve ekleme -rseçeneği rm.

In bashkullanmak, rm -- !(file.txt)şunları yapmalısınız extglob etkinleştirmek :

$ shopt -s extglob 
$ rm -- !(file.txt)

(veya arayarak bash -O extglob)

extglobSadece bashKorn kabuk ailesinde çalıştığını unutmayın . Ve kullanmak rm -- !(file.txt)bir Argument list too longhataya neden olabilir .

In zsh, ExtendedGlob etkinken ^kalıbı olumsuzlamak için kullanabilirsiniz :

$ setopt extendedglob
$ rm -- ^file.txt

ya ile aynı sözdizimini kullanarak kshve bashseçenekleri ile ksh_globve no_bare_glob_qualetkin.


9
Dizini belirtmek iyi bir uygulamadır (bu durumda tam yol nedir? Veya bu komutun geçerli çalışma dizininden başlayarak her dosyayı sildiği konusunda bir uyarı ekleyin ?). Ben de genellikle herhangi bir örnek yazma rmolarak echo rmyerine ve onlar ne istediklerini yapacak gerçekten emin olduğunda sadece yankı çıkarmak insanlara sorun. Bunun dışında, tam cevap için + 1
Olivier Dulac

11
Hatırlamak -deleteyerine -exec, daha kısa ve hatırlamak daha kolay öneriyorum
Izkata

6
@ Izkata: -deletePOSIX tarafından tanımlanmadı.
cuonglm

5
Dosya listesi nasıl hariç tutulur?
Meysam

5
@Meysam - Bir dosya listesi işleyecek bir çözüm için cevabımı bakın. Gnouc'un findçözümüyle birlikte yapabileceğiniz şeyler ! \( -name one_file -o -name two_file \).
mikeserv

112

Başka bir yönden farklı bir yönelim (dosya isimlerinde boşluk yoksa)

ls | grep -v file.txt | xargs rm

veya (dosya adlarında boşluk olsa bile çalışır)

ls | grep -v file.txt | parallel rm

from man grep:

 -v, --invert-match
          Invert the sense of matching, to select non-matching lines.  (-v is specified by POSIX)

2
Dosya adlarında boşluk varsa işe yaramaz ...
Matteo

1
Ciao @Matteo, boşluk içeren dosyalar için de geçerlidir, ancak grep desenini tırnak işaretleri ile çevrelemeniz gerekir, örn ls | grep -v "a file with spaces.bin" | xargs rm. Bu normal bir grepsözdizimidir.
Sebastian,

1
@Sebastian Sorun, grepama değil rm. rmboşlukla ayrılmış bağımsız değişkenlerin bir listesini alır. Deneyin touch 'a b'; touch 'c d'; ls | grep -v 'a b' | xargs rm: alacaksınız rm: c: No such file or directoryverm: d: No such file or directory
Matteo

1
Evet, bu yaygın bir sorundur. Seçeneklere bakın -print0içinde findve -0içinde xargs. İşte bir geçici çözüm, ancak biraz rahatsız edici. find . -maxdepth 1 -type f | grep -v 'a b' | tr '\n' '\0' | xargs -0 rm. Bu arada, gnu parallelbu durumu iyi idare ediyor (neredeyse her zaman xargs'ın yerine geçiyorum:ls | grep -v 'a b' | parallel rm
Sebastian

1
Sadece boşluklar değil, hepsi boşluklar ve yeni satırlar değil, aynı zamanda karakterleri (tek, çift tırnak ve ters eğik çizgi) ve başlayarak dosyalardan alıntılar yapar -.
Stéphane Chazelas

32

Bir kopyasını sakla, her şeyi sil, kopyayı geri yükle:

{   rm -rf *
    tar -x
} <<TAR
$(tar -c $one_file)
TAR

Bir satırda:

{ rm -rf *; tar -x; } <<< $(tar -c $one_file)

Ancak bu burada dizeleri destekleyen bir kabuk gerektirir.


10
Bu biraz akıllara durgunluk veriyor.
vschum

2
@Derek - lütfen düzenlemeye bakın.
mikeserv

2
Ancak bu işlem yarıda kesilirse veya başka bir şey ters giderse, dosya gider.
kasperd

2
@ kasperd - hayır. Yalnızca ana kabuk çalıştığı zaman arasında ölürse rmve tar -x. rmistediği kadar başarısız olabilir.
mikeserv

2
Başka bir dizine taşımak ve geri taşımak daha verimli değil mi? Dosyanın içeriğiyle ilgilenmemize gerek yok, yalnızca yoluyla.
leonbloy

23

hepiniz bunu düşünüyorsunuz.

cd ..
mv fulldir/file.txt /tmp/
rm -rf fulldir
mkdir fulldir
mv /tmp/file.txt fulldir/

Bitti.

EDIT Aslında daha kolay:

cd ..
ln fulldir/file.txt ./
rm -rf fulldir
mkdir -p fulldir
mv file.txt fulldir/

3
Cevabımın yaptığı aynı şey. exce [pt dir. üzerindeki izinleri kaybetmez.
mikeserv

6
Ayrı bir dosya sistemindeki / tmp dizinindeki büyük bir dosyaysa ve her şeyi dosya sisteminin kökünden aşağıya kaldırmaya çalışıyorsanız, onu güvenli bir yere taşımak bir seçenek olmayabilir.
Johnny

1
Bu kesinlikle en basit cevap.
Ben Liyanage

17

Scientific Linux 6 işletim sistemimde bu çalışıyor:

shopt -s extglob
rm !(file.txt)

Ayrıca Sanal Makinede Debian 32bit yüklü. Yukarıdaki çalışmıyor ama aşağıdakiler çalışıyor:

find . -type f ! -name 'file.txt' -delete

1
Verdiğim findçözüm işe yaramadı mı demek istiyorsun?
cuonglm

"işe yaramadı" ya da "işe yaramadı". Evet, çözümün de işe yarıyor. Teşekkürler.
Kantura

1
Daha fazla ayrıntı yapabilir misin? "Nasıl işe yaramadı? Diğer dosyaları kaldırmadı ya da kaldırdı file.txtya da başka bir şey değil mi?
cuonglm

Demek istediğim Debian işletim sisteminde "$ rm! (File.txt)", "Badly yerleştirilmiş () 'ler" i veriyor. Bu yüzden "$ shopt -s extglob" ı denedim, ama geri döndü: "shopt: Command bulunamadı". Sonra "Bul" çözümünü denedim. Çalışıyor.
Kantura

1
Oh, elbette işe yaramıyor. shoptbir tcshyerleşik değil .
cuonglm

10

Yerine rm !("file.txt")kullanınrm !(file.txt)


4
Bu kesinlikle hiçbir farketmez. Buradaki sorun, OP'nin 1) bu formatı destekleyen bir kabuk kullanmaması ve 2) bash'de bile etkinleştirmeniz gerektiği idi shopt -s extglob. Her durumda, bunun gibi basit bir dosya adından alıntı yapmak bir fark yaratmazdı.
terdon

1
Sadece utils klasörü tutmak için - rm -rf! ("
Utils

7

Sadece farklı bir cevap vermek için, rmklasörleri silmeyeceği varsayılan davranışını kullanabilirsiniz :

mkdir tmp && mv file.txt tmp  # create tmp dir and move files there
rm                            # delete all other files
mv tmp/* . && rm -rf tmp      # move all files back and delete tmp dir

1

Bu yaklaşımın çok basit olduğunu, işe yaradığını ve özel bir uzantı gerektirmediğini biliyorum (bildiğim kadarıyla!)

ls --hide=file.txt | xargs rm
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.