Os.walk में निर्देशिका को छोड़कर


147

मैं एक स्क्रिप्ट लिख रहा हूं जो एक डायरेक्टरी ट्री (os.walk () का उपयोग करके) में उतरता है और फिर एक निश्चित फ़ाइल एक्सटेंशन से मेल खाते प्रत्येक फ़ाइल पर जाता है। हालाँकि, कुछ निर्देशिका पेड़ों का उपयोग किया जाता है, जिनमें मेरे उपकरण का उपयोग उप निर्देशिकाओं में भी होता है, जिनमें बदले में बहुत सारा बेकार (इस स्क्रिप्ट के उद्देश्य के लिए) सामान होता है, मुझे लगा कि मैं उपयोगकर्ता को निर्दिष्ट करने के लिए एक विकल्प जोड़ूंगा ट्रैवर्सल से बाहर करने के लिए निर्देशिकाओं की एक सूची।

यह os.walk () के साथ काफी आसान है। आखिरकार, यह मुझे तय करना है कि क्या मैं वास्तव में संबंधित फाइलों / dirs पर जाना चाहता हूं जो os.walk () द्वारा उत्पादित हैं या बस उन्हें छोड़ दें। समस्या यह है कि अगर मेरे पास है, उदाहरण के लिए, इस तरह एक निर्देशिका पेड़:

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

और मैं बेकार बेकार और उसके सभी बच्चों को बाहर करना चाहता हूं , os.walk () अभी भी बेकार के सभी (संभावित हजारों) उप निर्देशिकाओं में उतर जाएगा , जो कहने की जरूरत नहीं है, चीजों को बहुत धीमा कर देती है। एक आदर्श दुनिया में, मैं os.walk () को बेकार के किसी भी अधिक बच्चों को उपजाने से परेशान नहीं करने के लिए कह सकता हूं , लेकिन मेरे ज्ञान के लिए ऐसा करने का कोई तरीका नहीं है (क्या है?)।

क्या किसी को कुछ पता है? हो सकता है कि कोई तृतीय-पक्ष पुस्तकालय ऐसा कुछ प्रदान करता हो?

जवाबों:


242

dirs इन-प्लेस (बाद में) फ़ाइलों और निर्देशिकाओं को संशोधित करके इन-प्लेस को संशोधित किया जाएगा os.walk:

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

मदद से (os.walk):

जब टॉपडाउन सही होता है, तो कॉलर dirnames लिस्ट को इन-प्लेस (जैसे, डेल या स्लाइस असाइनमेंट के माध्यम से) संशोधित कर सकता है, और वॉक केवल उन सबडायरेक्टरीज में फिर से आ जाएगा, जिनके नाम dirnames में बने हुए हैं; इस खोज को prune करने के लिए इस्तेमाल किया जा सकता है ...


31
क्यों dirs[:] =?
बेन

56
@बेन: इन-प्लेसdirs[:] = value को संशोधित करता dirs है । यह dirsकंटेनर को बदले बिना सूची की सामग्री को बदलता है। help(os.walk)उल्लेख के रूप में, यह आवश्यक है यदि आप os.walkउपनिर्देशिकाओं को प्रभावित करने के तरीके को प्रभावित करना चाहते हैं । ( मूल को संशोधित किए बिना एक नई सूची dirs = valueमें चर dirsको केवल पुन: असाइन करें (या "बाइंड") dirs।)
unutbu

6
आप इसका उपयोग भी कर सकते हैं filter():dirs[:] = list(filter(lambda x: not x in exclude, dirs))
न्यूक्लियरपॉन

2
@ p014k: आप अपना खुद का जनरेटर फ़ंक्शन लिख सकते हैं, जिसमें कॉल os.walkऔर पैदावार root, dirs, filesको छोड़कर .git(या जो कुछ भी आप चाहते हैं) dirs
unutbu

3
@unutbu बस आपको बता दें कि एक मामले में, इस अनुकूलन ने ट्रैवर्सल समय को 100 सेकंड से कम करके लगभग 2 सेकंड कर दिया है। यही मैं एक सार्थक अनुकूलन कहता हूं। : D
१३:१६

7

... @ अनटुब के उत्कृष्ट उत्तर का एक वैकल्पिक रूप जो थोड़ा और सीधे पढ़ता है, यह देखते हुए कि ओ (एन ** 2) बनाम ओ (एन) की कीमत पर, निर्देशिका को बाहर करना है।

( list(dirs)सही निष्पादन के लिए dirs सूची की एक प्रति बनाना आवश्यक है)

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

5
यदि आप कुछ मेमोरी की कीमत पर अधिक प्रत्यक्ष होना चाहते हैं, तो आप बेहतर लिखेंगे dirs[:] = set(dirs) - exclude। कम से कम यह अभी भी \ $ O (n) \ $ है और आप इसके दुष्प्रभावों के लिए केवल एक समझ का निर्माण नहीं करते ...
301_Moved_Permanently

3
यह वास्तव में बुरा नहीं है, लेकिन मेरी राय में मुहावरेदार नहीं है।
टॉरस्टेन ब्रॉन्गर

for d in list(dirs)थोड़ा अजीब है। dirsपहले से ही एक सूची है। और जो आपके पास है वह वास्तव में सूची बोध नहीं है। dirs.remove(d)कुछ भी वापस नहीं करता है, इसलिए आप पूरी सूची के साथ समाप्त होते हैं None। मैं @Torsten से सहमत हूँ।
शॉनहेरन
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.