नीचे निर्देशिका में खुदाई के बिना os.walk


103

मैं os.walkजो निर्देशिका प्रदान करता हूं, उसमें केवल फाइलों को वापस करने की सीमा कैसे तय करूं ?

def _dir_list(self, dir_name, whitelist):
    outputList = []
    for root, dirs, files in os.walk(dir_name):
        for f in files:
            if os.path.splitext(f)[1] in whitelist:
                outputList.append(os.path.join(root, f))
            else:
                self._email_to_("ignore")
    return outputList

2
एक और मामला जहां संभावित दृष्टिकोणों की भीड़ और उनके साथ जाने वाले सभी गुहाओं का सुझाव है कि इस कार्यक्षमता को पायथन मानक पुस्तकालय में जोड़ा जाना चाहिए।
प्राचीन

files_with_full_path = [f.path for f in os.scandir(dir) if f.is_file()]। मामले में आपको केवल फ़ाइल नाम का उपयोग f.nameकरने की आवश्यकता है f.path। यह सबसे तेजी से समाधान और बहुत तेजी से किसी से भी अधिक है walkया listdir, देख stackoverflow.com/a/40347279/2441026
user136036

जवाबों:


105

walklevelफ़ंक्शन का उपयोग करें ।

import os

def walklevel(some_dir, level=1):
    some_dir = some_dir.rstrip(os.path.sep)
    assert os.path.isdir(some_dir)
    num_sep = some_dir.count(os.path.sep)
    for root, dirs, files in os.walk(some_dir):
        yield root, dirs, files
        num_sep_this = root.count(os.path.sep)
        if num_sep + level <= num_sep_this:
            del dirs[:]

यह बिल्कुल काम करता है os.walk, लेकिन आप इसे एक levelपैरामीटर पास कर सकते हैं जो बताता है कि रिकर्सन कितना गहरा जाएगा।


3
क्या यह फ़ंक्शन वास्तव में पूरे ढांचे के माध्यम से "चलता है" और फिर एक निश्चित बिंदु से नीचे की प्रविष्टियों को हटा देता है? या कुछ ज्यादा ही चतुर है? मुझे यह भी पता नहीं है कि कोड के साथ यह कैसे जांचना है। --pyth शुरुआत
mathtick

1
@ मैथटिक: जब वांछित स्तर पर या उससे नीचे की कोई निर्देशिका मिलती है, तो उसके सभी उपखंडों को अगली खोज करने के लिए उप-अध्यक्षों की सूची से हटा दिया जाता है। तो वे "चल" नहीं जाएंगे।
nosklo

2
मैंने इसे केवल "1" किया क्योंकि मैं कैसे "डिलीट" डायर के साथ संघर्ष कर रहा था। मैंने कोशिश की थी dirs = []और dirs = Noneउन लोगों ने काम नहीं किया। map(dirs.remove, dirs)काम किया, लेकिन कुछ अवांछित '[कोई नहीं]' संदेशों के साथ। तो, del dirs[:]विशेष रूप से क्यों ?
जैच यंग

4
ध्यान दें कि यह काम नहीं करता है जब topdown=Falseos.walk में उपयोग किया जाता है। डॉक्स में 4 वें पैराग्राफ को देखें :Modifying dirnames when topdown is False has no effect on the behavior of the walk, because in bottom-up mode the directories in dirnames are generated before dirpath itself is generated.
dthor

3
@ZacharyYoung dirs = []और dirs = Noneकाम नहीं करेगा क्योंकि वे सिर्फ एक नई असंबंधित वस्तु बनाते हैं और नाम को निर्दिष्ट करते हैं dirs। मूल सूची ऑब्जेक्ट को नाम में नहीं, बल्कि इन-प्लेस संशोधित करना होगा dirs
nosklo

206

Os.walk का उपयोग न करें।

उदाहरण:

import os

root = "C:\\"
for item in os.listdir(root):
    if os.path.isfile(os.path.join(root, item)):
        print item

1
@ 576i: यह फाइलों और निर्देशिकाओं के बीच अंतर नहीं करता है

4
@ अलेक्जेंडर os.path.isfileऔर os.path.isdirआपको अंतर करने देता है। मुझे यह नहीं मिला, os.path.isfileक्योंकि '08 के बाद से नमूना कोड में है और आपकी टिप्पणी '16 से है। यह स्पष्ट रूप से बेहतर उत्तर है, क्योंकि आप एक निर्देशिका को चलना नहीं चाहते हैं, लेकिन इसे सूचीबद्ध करने के लिए।
डैनियल एफ

@DanielF, मेरा यहाँ क्या मतलब है कि आपको सभी वस्तुओं पर लूप करने की आवश्यकता है, जबकि walkआपको तुरंत ही डायरियों और फाइलों की अलग-अलग सूचियाँ मिल जाती हैं।

आह अच्छा। वास्तव में एलेक्स का जवाब बेहतर (उपयोग .next()) लगता है और यह आपके विचार के बहुत करीब है।
डैनियल एफ

पायथन 3.5 में एक os.scandirफ़ंक्शन होता है जो अधिक परिष्कृत फ़ाइल-या-डायरेक्टरी-ऑब्जेक्ट इंटरैक्शन की अनुमति देता है। देखें मेरा उत्तर नीचे
ascripter

48

मुझे लगता है कि समाधान वास्तव में बहुत सरल है।

उपयोग

break

केवल लूप के लिए पहली पुनरावृत्ति करने के लिए, अधिक सुरुचिपूर्ण तरीका होना चाहिए।

for root, dirs, files in os.walk(dir_name):
    for f in files:
        ...
        ...
    break
...

पहली बार जब आप os.walk कहते हैं, तो यह वर्तमान निर्देशिका के लिए ट्यूलिप देता है, फिर अगले लूप पर अगली निर्देशिका की सामग्री।

मूल स्क्रिप्ट लें और बस एक ब्रेक जोड़ें ।

def _dir_list(self, dir_name, whitelist):
    outputList = []
    for root, dirs, files in os.walk(dir_name):
        for f in files:
            if os.path.splitext(f)[1] in whitelist:
                outputList.append(os.path.join(root, f))
            else:
                self._email_to_("ignore")
        break
    return outputList

9
यह स्वीकृत उत्तर होना चाहिए था। बस "फाइलों में एफ के लिए" के बाद "ब्रेक" जोड़ने से लूप पुनरावृत्ति को रोकता है। आप यह भी सुनिश्चित करना चाहेंगे कि टॉपडाउन = ट्रू।
एलेक्सी

23

उपयोग करने का सुझाव listdirएक अच्छा है। पायथन 2 में आपके प्रश्न का सीधा उत्तर है root, dirs, files = os.walk(dir_name).next()

बराबर पायथन 3 सिंटेक्स है root, dirs, files = next(os.walk(dir_name))


1
ओह, मैं उस एक से सभी प्रकार की अजीब त्रुटि प्राप्त कर रहा था। ValueRrror: बहुत सारे मान अनपैक करने के लिए
Setori

1
अच्छा! एक हैक की तरह महसूस करता है, हालांकि। जैसे कि जब आप एक इंजन चालू करते हैं, लेकिन केवल इसे एक क्रांति करने देते हैं और फिर इसे मरने के लिए कुंजी खींचते हैं।
डैनियल एफ

इस पार ठोकर लगी; root, dirs, files = os.walk(dir_name).next()मुझे देता हैAttributeError: 'generator' object has no attribute 'next'
इवान

3
@ इवान, शायद क्योंकि यह 2008 से है और पायथन 2 सिंटैक्स का उपयोग करता है। पायथन 3 में आप लिख सकते हैं root, dirs, files = next(os.walk(dir_name))और तब चर root, dirs, filesकेवल dir_nameस्तर पर जनरेटर के चर के अनुरूप होंगे ।
CervEd

13

आप os.listdir()दी गई निर्देशिका में नामों की सूची (फाइल और निर्देशिका दोनों के लिए) का उपयोग कर सकते हैं । यदि आपको फ़ाइलों और निर्देशिकाओं के बीच अंतर करने की आवश्यकता है, तो os.stat()प्रत्येक नाम पर कॉल करें ।


9

यदि आपके पास शीर्ष निर्देशिका की तुलना में अधिक जटिल आवश्यकताएं हैं (जैसे VCS dirs आदि को अनदेखा करें), तो आप उनके माध्यम से os.walk को रोकने के लिए निर्देशिकाओं की सूची को भी संशोधित कर सकते हैं।

अर्थात:

def _dir_list(self, dir_name, whitelist):
    outputList = []
    for root, dirs, files in os.walk(dir_name):
        dirs[:] = [d for d in dirs if is_good(d)]
        for f in files:
            do_stuff()

नोट - सिर्फ रिबंड करने के बजाय सूची को म्यूट करने के लिए सावधान रहें। जाहिर तौर पर os.walk बाहरी विद्रोह के बारे में नहीं जानता है।




3

लगा जैसे मेरा 2 पेंस अंदर फेंक दिया हो।

baselevel = len(rootdir.split("\\"))
for subdirs, dirs, files in os.walk(rootdir):
    curlevel = len(subdirs.split("\\"))
    if curlevel <= baselevel + 1:
        [do stuff]

2

पायथन 3 में, मैं यह करने में सक्षम था:

import os
dir = "/path/to/files/"

#List all files immediately under this folder:
print ( next( os.walk(dir) )[2] )

#List all folders immediately under this folder:
print ( next( os.walk(dir) )[1] )

यह पायथन 2 के लिए भी काम करता है। दूसरा स्तर कैसे प्राप्त करें?

2

पायथन 3.5 के बाद से आप os.scandirइसके बजाय उपयोग कर सकते हैं os.listdir। तार के बजाय आपको DirEntryबदले में वस्तुओं का एक पुनरावृत्ति मिलता है । डॉक्स से:

scandir()इसके बजाय उपयोग करने से listdir()कोड के प्रदर्शन में काफी वृद्धि हो सकती है जिसमें फ़ाइल प्रकार या फ़ाइल विशेषता जानकारी की भी आवश्यकता होती है, क्योंकि DirEntryऑब्जेक्ट इस जानकारी को उजागर करते हैं यदि ऑपरेटिंग सिस्टम किसी निर्देशिका को स्कैन करते समय प्रदान करता है। सभी DirEntryतरीकों एक सिस्टम कॉल प्रदर्शन कर सकते हैं, लेकिन is_dir()और is_file()आमतौर पर केवल सांकेतिक लिंक के लिए एक प्रणाली कॉल आवश्यकता होती है; DirEntry.stat()हमेशा यूनिक्स पर एक सिस्टम कॉल की आवश्यकता होती है, लेकिन केवल विंडोज पर प्रतीकात्मक लिंक के लिए एक की आवश्यकता होती है।

आप उस वस्तु के नाम तक पहुँच सकते हैं DirEntry.nameजिसके द्वारा तब के आउटपुट के बराबर हैos.listdir


1
न केवल "आप" का उपयोग कर सकते हैं, आपको उपयोग करना चाहिएscandir() , क्योंकि यह बहुत तेज़ है listdir()। मानक यहाँ देखें: stackoverflow.com/a/40347279/2441026
user136036

1

आप निम्न कार्य भी कर सकते हैं:

for path, subdirs, files in os.walk(dir_name):
    for name in files:
        if path == ".": #this will filter the files in the current directory
             #code here

2
सभी उप-डायर और अनावश्यक रूप से फ़ाइलों के माध्यम से यह लूप नहीं होगा?
Pieter

0

इस तरह मैंने इसे हल किया

if recursive:
    items = os.walk(target_directory)
else:
    items = [next(os.walk(target_directory))]

...

0

Listdir का उपयोग करते समय एक पकड़ है। Os.path.isdir (पहचानकर्ता) एक पूर्ण पथ होना चाहिए। उपनिर्देशिका लेने के लिए आप क्या करें:

for dirname in os.listdir(rootdir):
  if os.path.isdir(os.path.join(rootdir, dirname)):
     print("I got a subdirectory: %s" % dirname)

विकल्प को os.path.join () के बिना परीक्षण करने के लिए निर्देशिका में बदलना है।


0

आप इस स्निपेट का उपयोग कर सकते हैं

for root, dirs, files in os.walk(directory):
    if level > 0:
        # do some stuff
    else:
        break
    level-=1

0

बहिष्करण की एक सूची बनाएं, निर्देशिका संरचना को छोड़ने और प्रक्रिया करने के लिए fnmatch का उपयोग करें

excludes= ['a\*\b', 'c\d\e']
for root, directories, files in os.walk('Start_Folder'):
    if not any(fnmatch.fnmatch(nf_root, pattern) for pattern in excludes):
        for root, directories, files in os.walk(nf_root):
            ....
            do the process
            ....

'शामिल' के लिए भी:

if **any**(fnmatch.fnmatch(nf_root, pattern) for pattern in **includes**):

0

क्यों नहीं बस एक का उपयोग करें rangeऔर os.walkके साथ संयुक्त zip? सबसे अच्छा समाधान नहीं है, लेकिन यह भी काम करेगा।

इस तरह के उदाहरण के लिए:

# your part before
for count, (root, dirs, files) in zip(range(0, 1), os.walk(dir_name)):
    # logic stuff
# your later part

मेरे लिए अजगर 3 पर काम करता है।

भी: एक breakसरल भी btw है। (@Pieter से जवाब देखें)


0

एलेक्स के जवाब में थोड़ा बदलाव, लेकिन उपयोग करना __next__():

print(next(os.walk('d:/'))[2]) या print(os.walk('d:/').__next__()[2])

अन्य उत्तरों में उल्लिखित [2]होने के साथfileroot, dirs, file


0

रूट फ़ोल्डर में हर निर्देशिका के लिए परिवर्तन होता है। os.walk पाता है। मैं सॉल्व करता हूं कि अगर रूट == डायरेक्टरी को चेक किया जाए

def _dir_list(self, dir_name, whitelist):
    outputList = []
    for root, dirs, files in os.walk(dir_name):
        if root == dir_name: #This only meet parent folder
            for f in files:
                if os.path.splitext(f)[1] in whitelist:
                    outputList.append(os.path.join(root, f))
                else:
                    self._email_to_("ignore")
    return outputList

0
import os

def listFiles(self, dir_name):
    names = []
    for root, directory, files in os.walk(dir_name):
        if root == dir_name:
            for name in files:
                names.append(name)
    return names

1
हाय रिच, ढेर अतिप्रवाह में आपका स्वागत है! इस कोड स्निपेट के लिए धन्यवाद, जो कुछ सीमित अल्पकालिक सहायता प्रदान कर सकता है। एक उचित व्याख्या यह दर्शाती है कि यह समस्या का एक अच्छा समाधान क्यों है, यह दिखा कर इसके दीर्घकालिक मूल्य में बहुत सुधार होगा , और यह भविष्य के पाठकों को अन्य, समान प्रश्नों के साथ और अधिक उपयोगी बना देगा। कृपया कुछ स्पष्टीकरण जोड़ने के लिए अपने उत्तर को संपादित करें, जिसमें आपके द्वारा की गई धारणाएँ शामिल हैं।
kenny_k
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.