मैं ग्लोब.ग्लोब मॉड्यूल का उपयोग करके उप-फ़ोल्डर्स कैसे खोज सकता हूं?


107

मैं एक फ़ोल्डर में सबफ़ोल्डर्स की एक श्रृंखला खोलना चाहता हूं और कुछ पाठ फ़ाइलें ढूंढता हूं और पाठ फ़ाइलों की कुछ पंक्तियों को प्रिंट करता हूं। मैं इसका उपयोग कर रहा हूं:

configfiles = glob.glob('C:/Users/sam/Desktop/file1/*.txt')

लेकिन यह सबफ़ोल्डर्स तक भी नहीं पहुँच सकता है। क्या किसी को पता है कि मैं उसी कमांड का उपयोग सबफ़ोल्डर्स तक पहुंचने के लिए कैसे कर सकता हूं?


जवाबों:


163

पायथन 3.5 और नए में नई पुनरावर्ती **/कार्यक्षमता का उपयोग करें :

configfiles = glob.glob('C:/Users/sam/Desktop/file1/**/*.txt', recursive=True)

जब recursiveसेट **किया जाता है , उसके बाद एक पथ विभाजक 0 या अधिक उपनिर्देशिकाओं से मेल खाता है।

पहले पायथन संस्करणों में, glob.glob()उपनिर्देशिकाओं में फ़ाइलों को पुनरावर्ती रूप से सूचीबद्ध नहीं किया जा सकता है।

उस स्थिति में मैं इसके os.walk()साथ संयुक्त उपयोग करूँगा fnmatch.filter():

import os
import fnmatch

path = 'C:/Users/sam/Desktop/file1'

configfiles = [os.path.join(dirpath, f)
    for dirpath, dirnames, files in os.walk(path)
    for f in fnmatch.filter(files, '*.txt')]

यह आपकी निर्देशिकाओं को पुनरावर्ती रूप से चलाएगा और सभी पूर्ण पथनामों को मिलान वाली .txtफ़ाइलों पर लौटाएगा । इस विशिष्ट मामले में fnmatch.filter()ओवरकिल हो सकता है, आप एक .endswith()परीक्षण का उपयोग भी कर सकते हैं :

import os

path = 'C:/Users/sam/Desktop/file1'

configfiles = [os.path.join(dirpath, f)
    for dirpath, dirnames, files in os.walk(path)
    for f in files if f.endswith('.txt')]

3
मैं देख सकता हूं: मेरे लिए काम कर रहे glob.glob ('निर्देशिका का पथ / * / * * txt ") । यह बेसिक्स का उपयोग यूनिक्स खोल नियम का उपयोग कर रहा है।
सूर्या

7
@ User123: यह सूची निर्देशिकाओं की पुनरावृत्ति नहीं करता है । आप सभी पाठ फ़ाइलों को एक स्तर गहरे में सूचीबद्ध कर रहे हैं , लेकिन आगे उपनिर्देशिकाओं में या सीधे भी नहीं path to directory
मार्टिन पीटर्स

1
यह पूरी तरह से संबंधित नहीं है, लेकिन कार्यक्षमता के recursive=Falseसाथ सेटिंग **/केवल दिए गए फ़ोल्डर में फ़ाइलों की सूची प्रदान नहीं करता है, बल्कि इसके बच्चों में क्यों है?
Dr_Zaszuś

@ Dr_Zaszuś: क्षमा करें? वर्तमान कार्यशील निर्देशिका में निर्देशिका नामों**/ की एक सूची देता है , क्योंकि पैटर्न में समाप्त होता है , और आपके साथ मूल रूप से एक डबल होता है , बस उसी तरह मेल खाता है , जैसे कम कुशल। /recursive=False**/
मार्टिज़न पीटरर्स

@ Dr_Zaszuś: */*यदि आपको सभी उपनिर्देशिकाओं में सभी फ़ाइलों की आवश्यकता है तो उपयोग करें ।
मार्टिन पीटर्स

22

तत्काल उपनिर्देशिकाओं में फ़ाइलों को खोजने के लिए:

configfiles = glob.glob(r'C:\Users\sam\Desktop\*\*.txt')

पुनरावर्ती संस्करण के लिए जो सभी उपनिर्देशिकाओं को पार करता है, आप पायथन 3.5 के बाद से उपयोग कर सकते हैं **और पास कर सकते हैं :recursive=True

configfiles = glob.glob(r'C:\Users\sam\Desktop\**\*.txt', recursive=True)

दोनों फ़ंक्शन कॉल सूची लौटाते हैं। आप glob.iglob()एक-एक करके रास्ते लौट सकते हैं । या उपयोग करेंpathlib :

from pathlib import Path

path = Path(r'C:\Users\sam\Desktop')
txt_files_only_subdirs = path.glob('*/*.txt')
txt_files_all_recursively = path.rglob('*.txt') # including the current dir

दोनों विधियां पुनरावृत्तियों को वापस करती हैं (आप एक-एक करके पथ प्राप्त कर सकते हैं)।


हाँ, मैं समझ गया था कि; लेकिन मुझे glob()निर्देशिकाओं में पैटर्न का समर्थन करने की उम्मीद नहीं थी ।
मार्टिन पीटर्स

टिप्पणी हटा दी गई, अब मैं देख रहा हूं कि इसने गलत प्रभाव डाला; इसके अलावा, पैच में **रिकर्सन केस के लिए प्रलेखन अद्यतन शामिल है । लेकिन के लिए **काम करने के लिए, आप है स्थापित करने के लिए recursion=True, स्विच btw।
मार्टिन पीटर्स

20

इस विषय पर बहुत भ्रम है। मुझे देखने दो कि क्या मैं इसे स्पष्ट कर सकता हूँ (अजगर 3.7):

  1. glob.glob('*.txt') :वर्तमान निर्देशिका में '.txt' में समाप्त होने वाली सभी फाइलों से मेल खाता है
  2. glob.glob('*/*.txt') :1 के समान
  3. glob.glob('**/*.txt') :केवल तत्काल उपनिर्देशिकाओं में '.txt' में समाप्त होने वाली सभी फ़ाइलों से मेल खाता है , लेकिन वर्तमान निर्देशिका में नहीं
  4. glob.glob('*.txt',recursive=True) :1 के समान
  5. glob.glob('*/*.txt',recursive=True) :3 के समान
  6. glob.glob('**/*.txt',recursive=True):वर्तमान निर्देशिका में और सभी उपनिर्देशिकाओं में '.txt' में समाप्त होने वाली सभी फाइलों से मेल खाता है

इसलिए यह हमेशा निर्दिष्ट करना सबसे अच्छा है recursive=True.


1
यह शीर्ष उत्तर होना चाहिए!
अभि सरकार

17

Glob2 पैकेज वाइल्ड कार्ड का समर्थन करता है और यथोचित तेज है

code = '''
import glob2
glob2.glob("files/*/**")
'''
timeit.timeit(code, number=1)

मेरे लैपटॉप पर > 60,000 फ़ाइल पथ से मिलान करने में लगभग 2 सेकंड लगते हैं



4

यहां एक अनुकूलित संस्करण है जो glob.globउपयोग किए बिना कार्यक्षमता की तरह सक्षम बनाता है glob2

def find_files(directory, pattern='*'):
    if not os.path.exists(directory):
        raise ValueError("Directory not found {}".format(directory))

    matches = []
    for root, dirnames, filenames in os.walk(directory):
        for filename in filenames:
            full_path = os.path.join(root, filename)
            if fnmatch.filter([full_path], pattern):
                matches.append(os.path.join(root, filename))
    return matches

तो अगर आपके पास निम्नलिखित dir संरचना है

tests/files
├── a0
   ├── a0.txt
   ├── a0.yaml
   └── b0
       ├── b0.yaml
       └── b00.yaml
└── a1

आप ऐसा कुछ कर सकते हैं

files = utils.find_files('tests/files','**/b0/b*.yaml')
> ['tests/files/a0/b0/b0.yaml', 'tests/files/a0/b0/b00.yaml']

fnmatchकेवल फ़ाइल नाम के बजाय पूरे फ़ाइल नाम पर बहुत अधिक प्रतिमान मेल खाते हैं।


2

configfiles = glob.glob('C:/Users/sam/Desktop/**/*.txt")

सभी मामलों के लिए काम नहीं करता है, इसके बजाय ग्लोब 2 का उपयोग करें

configfiles = glob2.glob('C:/Users/sam/Desktop/**/*.txt")

2

यदि आप glob2 पैकेज स्थापित कर सकते हैं ...

import glob2
filenames = glob2.glob("C:\\top_directory\\**\\*.ext")  # Where ext is a specific file extension
folders = glob2.glob("C:\\top_directory\\**\\")

सभी फ़ाइलनाम और फ़ोल्डर:

all_ff = glob2.glob("C:\\top_directory\\**\\**")  

2

यदि आप पायथन 3.4+ चला रहे हैं, तो आप pathlibमॉड्यूल का उपयोग कर सकते हैं । Path.glob()विधि का समर्थन करता है **पैटर्न है, जो अर्थ है "इस निर्देशिका और सभी सबडायरेक्टरियों, रिकर्सिवली"। यह Pathसभी मिलान फ़ाइलों के लिए एक जनरेटर उपज वस्तुओं देता है ।

from pathlib import Path
configfiles = Path("C:/Users/sam/Desktop/file1/").glob("**/*.txt")

0

जैसा कि मार्टिज़न द्वारा बताया गया है, ग्लोब केवल **पायथन 3.5 में शुरू किए गए ऑपरेटर के माध्यम से ऐसा कर सकता है । चूंकि ओपी ने स्पष्ट रूप से ग्लोब मॉड्यूल के लिए कहा है, इसलिए निम्न एक आलसी मूल्यांकन पुनरावृत्ति लौटाएगा जो समान व्यवहार करता है

import os, glob, itertools

configfiles = itertools.chain.from_iterable(glob.iglob(os.path.join(root,'*.txt'))
                         for root, dirs, files in os.walk('C:/Users/sam/Desktop/file1/'))

ध्यान दें कि आप configfilesइस दृष्टिकोण में केवल एक बार पुनरावृति कर सकते हैं । यदि आपको ऐसे कॉन्फिगर की वास्तविक सूची की आवश्यकता है जिसका उपयोग कई कार्यों में किया जा सकता है तो आपको इसका उपयोग करके स्पष्ट रूप से बनाना होगा list(configfiles)


0

कमांड rglobआपकी निर्देशिका संरचना के सबसे गहरे उप-स्तर के नीचे एक अनंत पुनरावृत्ति करेगा। यदि आप केवल एक स्तर को गहरा चाहते हैं, तो इसका उपयोग न करें, हालांकि।

मुझे पता है कि ओपी glob.glob का उपयोग करने के बारे में बात कर रहा था। मेरा मानना ​​है कि यह आशय का उत्तर देता है, जो कि सभी सबफ़ोल्डर्स को पुनरावर्ती रूप से खोजना है।

rglobसमारोह हाल ही में एक डाटा प्रोसेसिंग एल्गोरिथ्म जो पढ़ने डेटा के आदेश के लिए एक निश्चित धारणा के रूप में फ़ोल्डर संरचना उपयोग कर रहा था के लिए गति में एक 100x वृद्धि का उत्पादन किया। हालाँकि, rglobहम एक निर्दिष्ट पेरेंट निर्देशिका में या उससे नीचे की सभी फ़ाइलों के माध्यम से एक बार स्कैन करने में सक्षम थे, उनके नामों को एक सूची (एक मिलियन से अधिक फ़ाइलों) में सहेजें, फिर उस सूची का उपयोग यह निर्धारित करने के लिए करें कि हमें किन फ़ाइलों को खोलने की आवश्यकता है भविष्य में फ़ाइल नामकरण सम्मेलनों के आधार पर ही बनाम वे किस फ़ोल्डर में थे।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.