Bir dosya hariç belirli bir uzantıya sahip dosyaları terminalden kaldırma


36

"Filename.gif" adında bir dosya dışında .gif uzantılı tüm dosyaları kaldırmam gerekiyor. Bunu terminalde yapmanın en iyi yolu nedir?

Rm komutu *.gif, dosya dahil tüm gif dosyalarını siler filename.gif.

Yanıtlar:


66

İşte muhtemelen kullanmanız gereken basit çözüm:

mv filename.gif filename.gif.keep
rm *.gif
mv filename.gif.keep filename.gif

.keepUzantı ile ilgili özel bir şey yok , bu sadece dosya adını geçici olarak bitmeyecek şekilde yapıyor .gif.

Dosyayı yeniden adlandırmamanız gerekiyorsa (ve bunun önemli olduğu komut dosyası durumları vardır ):

for X in *.gif; do
    if [ "$X" != "filename.gif" ]; then
        rm "$X"
    fi
done

Veya bu şekilde daha kısa yazabilirsiniz:

for X in *.gif; do [ "$X" != "filename.gif" ] && rm "$X"; done

Bunun findyerine kullanmayı tercih edebilirsiniz ; Çok güçlü, sen belki daha okunabilir düşünün ve daha iyi kolları gibi karakterlerle garip dosya adları *onlarda .

find . -maxdepth 1 -not -name 'filename.gif' -name '*.gif' -delete

-notOperatörü okunabilirlik için kullandım , ancak POSIX uyumluluğu önemliyse - GNU find özelliğini kullanmıyorsanız veya bu bir komut dosyası içinse, başkalarına yeniden dağıtmayı veya çeşitli sistemlerde çalıştırmayı düşünüyorsunuz - kullanmak !yerine operatörü:

find . -maxdepth 1 ! -name 'filename.gif' -name '*.gif' -delete

Hakkında kullanışlı bir şey find, büyük / küçük harfe duyarsızlık komutunu kolayca değiştirebilmeniz ve böylece aşağıdaki gibi uzantıları olan dosyaları bulup silebilmesidir .GIF:

find . -maxdepth 1 -not -name 'filename.gif' -iname '*.gif' -delete

Kullandığım unutmayınız -inameyerine -namearama modeli için *.gifama var olmayan için kullandım filename.gif. Muhtemelen dosyanızın ne dendiğini tam olarak bilirsiniz ve -inameyalnızca uzantıda değil, dosya adının herhangi bir yerinde alternatif büyük / küçük harflerle eşleşir .

Tüm bu çözümler yalnızca geçerli dizinde bulunan dosyaları siler . Geçerli dizinde bulunmayan dosyaları silmezler ve geçerli dizinin alt dizinlerinde bulunan dosyaları silmezler.

Her yerde geçerli dizini içinde yer silme dosyaları isterseniz -, kullanım (vb vardır alt dizinleri dahil ve bu alt dizinleri alt dizinleri ve dosyaları geçerli dizin veya onun soyundan herhangi içinde bulunan) find olmadan maxdepth -1 :

find . -not -name 'filename.gif' -name '*.gif' -delete

Buna dikkat et!

Diğer değerleri de ile ayarlayabilirsiniz -maxdepth. Örneğin, geçerli dizindeki dosyaları ve alt öğelerini ve torunlarını silmek, ancak daha derinlerini silmek için:

find . -maxdepth 3 -not -name 'filename.gif' -name '*.gif' -delete

-deleteDiğer ifadelerden önce asla birinciyi koymamaya dikkat et ! Görüyorsun -deleteki, her zaman sonuna koydum . Baştan koyarsanız ilk önce değerlendirilir ve altındaki tüm dosyalar .(bitmeyen .gifdosyalar ve derin alt-alt-alt ... dizinleri dahil .) silinir!

Daha fazla bilgi için , manuel sayfalarına bakın bashve shbu örneklerde kullanılan komutlar için: mv, rm, [, ve (özellikle) find.


1
Sağol Eliah. Bu dosyayı, farklı bir biçimde dönüştürmek ve geri dönüştürmek için önerdiğiniz ilk yönteme benzer şekilde yaptım. Ama bu biraz alt optimal ve kirli görünüyordu. Siz ve @efthialex'in önerdiği ikinci yaklaşımı beğendim ve şimdi kullanıyorum. Teşekkürler!

1
@Marvis Bu ihtiyaçlarınızı karşıladığı için memnunum. Bu arada, bu cevabı find, çok yönlü olan başka bir metot (veya metot sınıfı) hakkındaki bilgilerle genişlettim .
Eliah Kagan

3
Detaylı cevap için teşekkürler findgerçekten iyi bir keşif.

1
Commonsense için +1 (move-delete-move) cevabı.
tu-Reinstate Monica-dor duh,

Nit-pick: Onlarda findtuhaf dosya adlarını *for-loop'dan daha iyi ele alır mı? For loop *, çift tırnak işaretleri kullandığınız için para cezası olan dosyaları işler .
Flimm

28

Kullanıyorsanız bash(varsayılan kabuk), extglobkabuk seçeneği genişletilmiş bir desen eşleştirme sözdizimi kullanmanızı sağlar. Etkinleştirmek için shoptbuiltin komutunu kullanın:

shopt -s extglob

(Bu satırı dosyama eklerim .bashrc.)

Diğer şeylerin yanı sıra !(), parenler içinde olmayan herhangi bir desenle eşleşen operatöre erişim sağlar . Amacınız için:

rm !(filename).gif

Daha fazla bilgiyi man bash"Desen Eşleştirme" başlığı altında bulabilirsiniz.


1
Mükemmel cevap! Bash özgüdür, bu nedenle taşınabilir komut dosyası için uygun olmayabilir, ancak etkileşimli görevler ve hatta bazı komut dosyaları için, bu işlem en iyi yoldur. extglobEtkinleştirilmesi gereken ek karmaşıklığı taşır , ancak devre dışı bırakıldığında kötü bir şey olmaz (bu durumda, bu işe yaramaz). Ve shopt -s extglob(veya global) yapılandırma dosyalarımın hiçbirinde bulunmasam da varsayılan olarak etkin görünüyor . Kutudan çıkarmamın neden işe yaradığına dair basit bir açıklama varsa, bu cevaba eklemek isteyebilirsiniz; ya da yeni bir soru gönderebilirim.
Eliah Kagan

13

Bir aç Terminal ile Ctrl+ Alt+ Tve türü:

find . -type f -name "*.gif" -and -not -name "filename.gif" -exec rm -vf {} \;

Arasındaki fark -deleteve -exec rm -vf {} \;ikinci seçeneği ile, sen nedeniyle, dosyalar kaldırılmış olduğunu görmek mümkün olacak olmasıdır -vbayrak. Bu -deleteseçenekle yapılamayan bir şey . ( -name -deleteDosya yazdırmak, ancak rmbirlikte -vher dosya olsaydı ortaya koymaktadır başarıyla silindi.)


1

Orada GLOBIGNOREdeğişkeni. Kimden man bash:

GLOBIGNORE
      A colon-separated list of patterns defining the set of filenames
      to be ignored by pathname expansion.  If a filename matched by a
      pathname expansion pattern also matches one of the  patterns  in
      GLOBIGNORE, it is removed from the list of matches.

Yani, basit bir yol söz GLOBGINOREkonusu dosya adına ayarlamaktır :

$ touch {a,b,c,d}.png
$ echo *.png
a.png b.png c.png d.png
$ GLOBIGNORE=c.png
$ echo *.png
a.png b.png d.png

Yani senin durumunda:

GLOBIGNORE=filename.gif; rm *.gif

Elbette GLOBIGNORE, desen içerdiğinden, bir deseni dışlamak istediğinizde kullanabilirsiniz:

$ GLOBIGNORE='[a-c].png'; echo *.png
d.png
$ touch bd.png; GLOBIGNORE='?.png'; echo *.png
bd.png

(?!) Bir avantajı ait GLOBIGNOREayarladığını otomatik Dahil Olmayanlar onu .ve.. eşleşmiş olan ve sağlayan dotglob:

The  GLOBIGNORE shell variable may be used to restrict the set of file‐
names matching a pattern.  If GLOBIGNORE is set, each matching filename
that also matches one of the patterns in GLOBIGNORE is removed from the
list of matches.  The filenames ``.''  and ``..''  are  always  ignored
when  GLOBIGNORE is set and not null.  However, setting GLOBIGNORE to a
non-null value has the effect of enabling the dotglob shell option,  so
all other filenames beginning with a ``.''  will match.  To get the old
behavior of ignoring filenames beginning with a ``.'', make ``.*''  one
of  the  patterns  in  GLOBIGNORE.  The dotglob option is disabled when
GLOBIGNORE is unset.

Bu nedenle, bir dizindeki tüm dosya ve klasörleri silmenin basit bir yolu :

GLOBIGNORE=.; rm -r *

Bu *, etkin .olduğundan beri başlayan dosya adlarıyla eşleşecek , ancak eşleşmeyecek veya bu nedenle ana dizini bu şekilde etkilemeyeceksiniz.GLOBIGNOREdotglob...

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.