Bir dizinde pdf uzantılı dosyalar hariç tüm dosyaları silin


50

Aşağıdakileri içeren bir dizini var:

x.pdf
y.zip
z.mp3
a.pdf

Ben dışında tüm dosyaları silmek istiyor x.pdfve a.pdf. Bunu terminalden nasıl yaparım? Hiçbir alt dizin bulunmadığından herhangi bir özyinelemeye gerek kalmaz.

Yanıtlar:


63
cd <the directory you want>
find . -type f ! -iname "*.pdf" -delete
  • İlk komut sizi dosyalarınızı silmek istediğiniz dizine götürecektir.
  • İkinci komut ile biten olanlar hariç tüm dosyaları silecektir .pdfdosya içinde

Örneğin, tempgiriş klasörünüzde adı verilen bir dizin varsa :

cd ~/temp

sonra dosyaları silin:

find . -type f ! -iname "*.pdf" -delete

Bu hariç tüm dosyaları silecektir xyz.pdf.

Bu iki komutu aşağıdakilerle birleştirebilirsiniz:

find ~/temp -type f ! -iname "*.pdf" -delete

.Geçerli dizin. Sonunda !olanlar hariç tüm dosyaları almak anlamına gelir .pdf. -type fdizinleri değil, sadece dosyaları seçer. -deletesilmek anlamına gelir.

NOT: Bu komut tüm dosyaları (pdf dosyaları hariç ama gizli dosyaları da içeren) geçerli dizindeki ve tüm alt dizinlerdeki silecektir. !daha önce gelmelisin -name. basitçe -namesadece içerecektir .pdfederken, -inameiçerecektir .pdfve.PDF

Yalnızca geçerli dizinde silmek ve alt dizinlerde silmek için şunu ekleyin -maxdepth 1:

find . -maxdepth 1 -type f ! -iname "*.pdf" -delete

Cevap için teşekkürler. Sözdizimini biraz anlamama yardım eder misin? ."ve" anlamına mı geliyor? !"hariç" -name, bir ad parametresiyle hariç tutmak istediğinizi belirtir ve ardından -deletebulma işlemi yapılacak mı? Yani "* .pdf" dışındaki her şeyi arar ve siler mi? Yoksa yanlış mı anladım?
jessenorton

.geçerli dizin anlamına gelir. sonunda !olanlar hariç tüm dosyaları almak anlamına gelir .pdf. -deletesilmek anlamına gelir. şimdi temiz miyim
Edward Torvalds

@ terdon Starkers, alt dizinlerin olmadığını söyledi. Hasta benden daha geniş olması için cevabımı düzenlemeyi bekle
Edward Torvalds

+1 -maxdepth 1Başlamak için parametreyi dahil etmiş olmalısınız . Ardından, yinelemeli olarak silmek istemeniz durumunda parametrenin çıkarılmasını önerin.
Tulains Córdova 12

3
bu benim dikkatimi çekmişti, -inameyerine kullanmamız gerekti -name, yoksa .PDFuzantısı olan dosyalar geçecek.
muru

43

İle bash'genişletilmiş kabuk globbing, seni dışındaki uzantılı dosyaları kaldırmak olabilir .pdfkullanılarak

rm -- *.!(pdf)

Pts tarafından belirtildiği gibi, --karakterler herhangi bir komut seçeneğinin sonunu belirtir, adı bir -karakterle başlayan ender dosyalarda komutu güvenli hale getirir .

Herhangi bir uzantıya sahip olmayan dosyaların yanı sıra uzantıları dışındaki dosyaların da silinmesini istiyorsanız .pdf, @DennisWilliamson tarafından belirtildiği gibi

rm -- !(*.pdf)

Genişletilmiş globbing varsayılan olarak etkin olmalıdır, ancak eğer

shopt -s extglob

Özellikle bunu bir betiğin içinde kullanmayı düşünüyorsanız, ifadenin hiçbir şeyle eşleşmemesi durumunda (yani dizinde pdf dosyası bulunmuyorsa), o zaman varsayılan olarak dünyaya genişletilmiş olarak geçilir. rmkomutu gibi bir hataya neden

rm: cannot remove `*.!(pdf)': No such file or directory

Bu varsayılan davranışı nullglobshell seçeneğini kullanarak değiştirebilirsiniz , ancak bunun kendi sorunu vardır. Daha ayrıntılı bir tartışma için bkz. NullGlob - Greg's Wiki


IMO'ya daha iyi yaklaşım.
Takkat

Uzantısız dosyalar ne olacak? FWIW, zsh içinderm *~*.pdf
Emil Jeřábek

1
Noktayı parantez içine koyardım.
Dennis Williamson,

4
Ah yıldız işareti de içeri olmalıdır: !(*.py). Ayrıca, muhtemelen OP sadece ".pdf" dosyalarının kalmasını istiyorsa, uzantısız dosyaları da silinmeli ve göz ardı edilmemelidir.
Dennis Williamson,

1
Bu yaklaşım, kabul edilen cevaptan daha basit ve düzenlidir.
Peter

18

Çöp kutusuna sil :

$ cd <the directory you want>
$ gvfs-trash !(*.pdf)

Veya mvkomut aracılığıyla (ancak bu şekilde .trashinfo bilgilerini kaydetmediğinden Çöp'ten geri yükleyemezsiniz, bu nedenle dosyalarınızı aşağıdaki gibi bir hedefe taşıdığınız anlamına gelir ).

mv !(*.pdf) ~/.local/share/Trash/files

6
Bu yaklaşım doğrudan kullanmaktan çok daha güvenlidir rm.
Seth

14

En kolay yaklaşım: Bir yerde başka bir dizin oluşturun (yalnızca bir dizinde siliyorsanız, yinelemeli değil, bir alt dizin bile olabilir); orada tüm .pdf's taşımak; her şeyi sil; pdf'in arkasını oynatın; ara dizini silin.

Çabuk, kolay, tam olarak ne yaptığınızı görebilirsiniz. Ara dizinin, temizlediğiniz dizininkiyle aynı aygıtta olduğundan emin olun, böylece hareketler kopya değil, adlardır!


4
+1 Yine acemi kullanıcı için anlamlı olan bir yorum için, bu kesinlikle istemeden dosyaları silmekle sonuçlanmayacaktır.
trognanders

4

Bash adlı kişiyi kullan:

GLOBIGNORE=x.pdf:a.pdf
rm *
unset GLOBIGNORE

Bash'ın man sayfasından:

GLOBIGNORE:

            Kümeyi tanımlayan bir iki nokta üst üste ayrılmış desen listesi
            dosya adı genişletmesi tarafından göz ardı edilecek dosya adlarının listesi.

Hızlı bir test:

mkdir /tmp/foooooo
cd /tmp/foooooo
touch x.pdf y.zip z.mp3 a.pdf
GLOBIGNORE=x.pdf:a.pdf
ls -1 *

Çıktı:

y.zip
z.mp3

3

Dikkatli olun ve oluşturun: xargs kullanın

İşte hoşuma giden bir yaklaşım, çünkü çok dikkatli olmamı sağlıyor: sadece silmek istediğim dosyaları gösterecek bir yol oluştur ve rmkullanmaya gönder xargs. Örneğin:

  • ls bana her şeyi gösterir
  • ls | grep pdfbana saklamak istediğim dosyaları gösteriyor. Hmm.
  • ls | grep -v pdftam tersini gösterir: saklamak istediğim hariç . Başka bir deyişle, silmek istediklerimin listesini gösterir. Tehlikeli bir şey yapmadan önce bunu onaylayabilirim.
  • ls | grep -v pdf | xargs rmtam olarak bu listeyi rmsilmek üzere gönderir

Dediğim gibi, çoğunlukla sağladığı güvenlik için bunu beğendim: rm *benim için kazara yok . Diğer iki avantaj:

  • Bu beste edilebilir; Tercihinize göre başlangıç ​​listesini lsveya kullanabilirsiniz find. İstediğiniz herhangi bir şeyi bu listeyi daraltma sürecinde kullanabilirsiniz - bir başkası grep, bir kısmı awkveya her neyse. Yalnızca adları renkli olan dosyaları silmeniz gerekirse, aynı şekilde oluşturabilirsiniz.
  • Her bir aracı ana amaç için kullanabilirsiniz. Bir bayrak kabul ettiğini hatırlamak zorunda kalmak yerine, findbulmak ve rmçıkarmak için kullanmayı tercih ederim . Ve bunu yaparsanız, yine alternatif çözümler oluşturabilirsiniz; belki de yerine , dosyayı çöp kutusuna taşıyan ("silinmeyi" sağlayan) ve bunun yerine pipoyu hareket ettiren bir komut oluşturabilirsiniz . Bu seçeneği desteklemene gerek yok , sadece işe yaradın.find-deletermtrashrmfind

Güncelleme

Bunun, dosya adlarındaki satır sonları, dosya isimleri my_pdfs.zip, vb.


4
Burada üç sorun fark ettim: a)pdf Adının herhangi bir yerinde bulunan herhangi bir dosyayı dışlar . --- b) Soneki harflerden herhangi biri büyük harf ise, PDF dosyalarını siler. --- c) Çıktısını kullanmak iyi bir fikir değildir ls. Yeni satırlar içeren dosya adlarıyla çalışmaz. lsÖzel karakterlerin yerine getirilmesinde kullanılan bazı uygulamalar, örneğin tab ?. --- Kullanımı daha iyidir: find -maxdepth 1 -print0. (çok kısa değil ls:) ----- grep -vi '\.pdf$'find -maxdepth 1 -print0 | grep -viz '\.pdf$' | xargs -0 rm
a'yı

1
Çözümü, birden fazla manuel yinelemeli "etkileşimli" bir süreç olarak kastettiğinizi anlıyorum, ancak uzun dosya listeleri için çekler zor kullanılabiliyor ve yukarıda belirtilen sorunlar hataları gözden kaçırmayı kolaylaştırabilir.
pabouk

1
@pabouk iyi puan; gerçek dünya her zaman işleri karmaşıklaştırır ve düzeltmeleriniz yardımcı olur. :) Ama hala bu genel yaklaşımın en iyisi olduğunu düşünüyorum. Her şeyi görsel olarak onaylamak için çok fazla dosya varsa, | head -20en azından kabaca doğru görünüp görünmediğini görebilirsiniz; oysa eğer sadece rm my_patternbüyük bir hata bulma şansınız olmaz.
Nathan Long

1
Dosyaları silmeden önce size gösterip, -delete dışında bırakıp sadece find . -type f ! -name "*.pdf"konsola yazdırmak veya daha az veya bir dosyaya aktarmak için bulmayı bulabilirsiniz . [ve daha sonra eğer pabouk'un yorumları gibi (eğer garip dosya isimleri için -print0 | ... -0 ile)
istenirse boruları xargs'a yönlendirin

3

Genellikle bu tür problemleri etkileşimli Python tercümanından çözerim:

mic@mic ~ $ python
>>> import os
>>> for f in os.listdir('.'):
...   if not f.endswith('.pdf'):
...     os.remove(f)

Tek bir astardan daha uzun olabilir findveya olabilir xargs, ancak son derece dayanıklıdır ve ilk önce araştırmak zorunda kalmadan tam olarak ne yaptığını biliyorum.


Her ek çizgi ile giderek gergin olsun isteyenler için, biz olabilir birine bunu yapmak:for item in [f for f in os.listdir('.') if not f.endswith('.pdf')]: os.remove(item)
Jacob Vlijm

python -c "import os; for f in os.listdir('.'): if not f.endswith('.pdf'): os.remove(f)"
mic_e

[os.remove(f) for f in os.listdir('.') if not f.endswith('.pdf')]
mic_e

Güzel! İkincisi bana bir sözdizimi hatası veriyor, nedenini anlama.
Jacob Vlijm

garip; Sistemimde hem python 3.4 ve python 2.7 ile çalışır.
mic_e

2

daha iyi cevap (önceki cevabımla kıyaslandığında) bu soruya güçlü filekomut kullanılarak verilecek .

$ file -i abc.pdf
abc: application/pdf; charset=binary

şimdi senin problemin:

cd <the directory you want to search in>
for var in ./*
do
if file -i "$var" | grep -q 'application/pdf\;'
then
echo "$var"
fi
done

forkomutun görevi, geçerli dizindeki dosyaları değişken biçiminde vermektir $var. if-thenkomut 0, file -i "$var" | grep -q 'application/pdf\;'komuttan çıkış durumunu alarak pdf dosyalarının adlarını çıkarır , 0yalnızca pdf dosyalarını bulursa çıkış durumunu verir .



1
rm -i -- !(*@(a|x).pdf)

Oku, a.pdfveya olmayan tüm dosyaları kaldır x.pdf.

Bu, 2 uzatılmış globun kullanılmasıyla çalışır, dışta !(), globun sonekten önce bir veya daha fazla aveya xpaternle eşleşmesini gerektiren, içerdiği globu olumsuzlar .pdf. Glob # extglob'a bakınız .

$ ls -a
.dotfile1 .dotfile2 a.pdf x.pdf y.zip z.mp3

$ echo -- !(a.pdf)
-- x.pdf y.zip z.mp3

$ echo -- !(x.pdf)
-- a.pdf y.zip z.mp3

$ echo -- !(a.pdf|x.pdf)
-- y.zip z.mp3

$ echo -- !(@(a|x).pdf)   # NOTE.that this matches the .dotfiles* as well
-- . .. .dotfile1 .dotfile2 y.zip z.mp3

$ echo -- !(*@(a|x).pdf)  # but this doesn't
-- y.zip z.mp3

$ echo rm -i -- !(*@(a|x).pdf)
rm -i -- y.zip z.mp3

1

taşınabilir kabuk yolu

$ ksh -c 'for i in ./*; do case $i in *.pdf)continue;; *)rm "$i";; esac;done'

Herhangi Bourne tarzı kabuğu ile hemen hemen POSIX ve uyumlu ( ksh, bash, dash). Portatif scriptler için uygun ve bashuzatılmış kabuk globbing kullanamadığınızda .

perl:

$ perl -le 'opendir(my $d,"."); foreach my $f (grep(-f && !/.pdf/ , readdir($d))){unlink $f};closedir $d'                                                             

Veya biraz daha temiz:

$ perl -le 'opendir(my $d,"."); map{ unlink $_ } grep(-f "./$_" && !/.pdf/ , readdir($d));closedir $d'

alternatif piton

python -c 'import os;map(lambda x: os.remove(x), filter(lambda x: not x.endswith(".pdf"),os.listdir(".")))'

0

Ne sildiğinize dikkat edin!

lsBazı yakalanmamış davranışlar istenmeyen dosyaları silebileceğinden, silmeyi denemeden önce sınamanın güvenli bir yolu önce sınamaktır . Ve doğrudan dizinin dışından yapabilirsiniz. lsbuna benzer rm:

ls sub/path/to/files/!(*.pdf)

Bu liste olacak

y.zip
z.mp3

Artık ne sildiğinizi görebilir ve bunları güvenle silebilirsiniz:

rm sub/path/to/files/!(*.pdf)

Ve bu kadar. *Yalnızca programlama dersi belgelerini saklamak gibi daha seçici olmak için joker kullanabilirsiniz :

rm sub/path/to/files/!(*programming*)
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.