Os.walk'taki dizinleri hariç tutma


154

Bir dizin ağacına inen (os.walk () kullanarak) ve ardından belirli bir dosya uzantısıyla eşleşen her dosyayı ziyaret eden bir komut dosyası yazıyorum. Ancak, benim araç aynı zamanda kendisi de bir içerdiğini alt dizinleri ihtiva üzerinde kullanılacağını dizin ağaçlarının bazı beri LOT şeyler (bu komut dosyası amacıyla) yararsız, ben kullanıcı belirtmek için ben bir seçenek eklemek düşündüm çapraz geçişten hariç tutulacak dizinlerin listesi.

Os.walk () ile bu yeterince kolaydır. Sonuçta, os.walk () tarafından sağlanan ilgili dosyaları / dizinleri gerçekten ziyaret etmek isteyip istemediğime veya onları atlayıp atmayacağıma karar vermek bana kalmıştır. Sorun şu ki, örneğin şuna benzer bir dizin ağacım varsa:

root--
     |
     --- dirA
     |
     --- dirB
     |
     --- uselessStuff --
                       |
                       --- moreJunk
                       |
                       --- yetMoreJunk

ve yararsızStuff'ı ve tüm alt öğelerini dışlamak istiyorum , os.walk () yine de yararsızStuff'ın tüm (potansiyel olarak binlerce) alt dizinine inecek , ki söylemeye gerek yok ki, işleri çok yavaşlatıyor. İdeal bir dünyada, os.walk () 'a artık işe yaramaz Stuff'tan daha fazla çocuk verme zahmetine girmemesini söyleyebilirdim , ama bildiğim kadarıyla bunu yapmanın bir yolu yok (var mı?).

Bir fikri olan var mı? Belki böyle bir şey sağlayan üçüncü taraf bir kitaplık vardır?

Yanıtlar:


251

Değiştirme dirs yerinde tarafından ziyaret (müteakip) dosyaları ve dizinleri erik olacak os.walk:

# exclude = set(['New folder', 'Windows', 'Desktop'])
for root, dirs, files in os.walk(top, topdown=True):
    dirs[:] = [d for d in dirs if d not in exclude]

Yardımdan (os.walk):

Yukarıdan aşağı doğru olduğunda, arayan kişi dizin adları listesini yerinde değiştirebilir (örneğin, del veya dilim ataması yoluyla) ve walk yalnızca adları dizinlerde kalan alt dizinlerde yinelenir; bu aramayı budamak için kullanılabilir ...


31
Neden dirs[:] =?
Ben

60
@ben: yerindedirs[:] = value değiştirir . Kabı değiştirmeden listenin içeriğini değiştirir. Gibi bahseder Eğer yolu etkileyecek istiyorsanız, bu gereklidir alt dizinleri erişir. ( orijinali değiştirmeden değişkeni yeni bir listeye yeniden dirs dirshelp(os.walk)os.walkdirs = valuedirsdirs
atar

7
Ayrıca şunları da kullanabilirsiniz filter():dirs[:] = list(filter(lambda x: not x in exclude, dirs))
NuclearPeon

2
@ p014k: Hariç tuttuktan sonra (veya başka ne isterseniz) çağıran os.walkve veren kendi jeneratör fonksiyonunuzu yazabilirsiniz . root, dirs, files.gitdirs
unutbu

3
@unutbu Sadece bir durumda, bu optimizasyonun geçiş süresini 100 saniyeden yaklaşık 2 saniyeye düşürdüğünü bilmenizi isterim. Ben buna değerli bir optimizasyon diyorum. : D
2016

7

... @ unutbu'nun , O (n ** 2) ve O (n) zamanı pahasına dizinleri dışlamak olduğu düşünüldüğünde, biraz daha doğrudan okuyan mükemmel cevabının alternatif bir biçimi .

( list(dirs)Doğru yürütme için dizin listesinin bir kopyasını oluşturmak gerekir)

# exclude = set([...])
for root, dirs, files in os.walk(top, topdown=True):
    [dirs.remove(d) for d in list(dirs) if d in exclude]

6
Biraz hafıza pahasına daha doğrudan olmak istiyorsan, yazsan iyi olur dirs[:] = set(dirs) - exclude. En azından hala \ $ O (n) \ $ ve sadece yan etkileri için bir anlayış geliştirmiyorsunuz ...
301_Moved_Permanently

3
Bu gerçekten kötü değil ama benim düşünceme göre deyimsel Python da değil.
Torsten Bronger

for d in list(dirs)biraz tuhaf. dirszaten bir liste. Ve sahip olduğun şey aslında bir liste anlayışı değil. dirs.remove(d)hiçbir şey döndürmez, bu nedenle e-postalarla dolu bir liste elde edersiniz None. @Torsten'e katılıyorum.
seanahern
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.