ग्लोब को छोड़कर पैटर्न


103

मैं अंदर फाइलों का एक समूह के साथ एक निर्देशिका है: eee2314, asd3442... और eph

मैं फ़ंक्शन के ephसाथ शुरू होने वाली सभी फ़ाइलों को बाहर करना चाहता हूं glob

मैं यह कैसे कर सकता हूं?

जवाबों:


146

ग्लोब के लिए पैटर्न नियम नियमित अभिव्यक्ति नहीं हैं। इसके बजाय, वे मानक यूनिक्स पथ विस्तार नियमों का पालन करते हैं। केवल कुछ विशेष वर्ण हैं: दो अलग-अलग वाइल्ड-कार्ड, और वर्ण श्रेणियां [ ग्लोब से ] समर्थित हैं ।

तो आप पैटर्न के साथ कुछ फ़ाइलों को बाहर कर सकते हैं।
उदाहरण के लिए _ग्लोब के साथ मैनिफ़ेस्ट फ़ाइल (फ़ाइलों से शुरू होने वाली ) को बाहर करने के लिए , आप उपयोग कर सकते हैं:

files = glob.glob('files_path/[!_]*')

10
यह आधिकारिक दस्तावेज़ीकरण पर होना चाहिए, कृपया कोई इसे docs.python.org/3.5/library/glob.html#glob.glob
विटाली ज़डेनविच

6
ध्यान दें कि ग्लोब पैटर्न ओपी द्वारा निर्धारित आवश्यकता को पूर्ण रूप से पूरा नहीं कर सकता है: केवल उन फ़ाइलों को बाहर करने के लिए जो इसके साथ शुरू होती हैं, ephलेकिन कुछ और के साथ शुरू हो सकती हैं। उदाहरण के लिए [!e][!p][!h]शुरू होने वाली फ़ाइलों को फ़िल्टर करेगा eee
मार्टिन पीटर्स

60

आप सेट घटा सकते हैं:

set(glob("*")) - set(glob("eph*"))

3
वास्तव में दिलचस्प समाधान! लेकिन दो बार पढ़ने के लिए मेरा मामला बेहद धीमा चल रहा है। इसके अलावा अगर किसी फ़ोल्डर की सामग्री नेटवर्क निर्देशिका पर बड़ी है, तो फिर से धीमा होने वाला है। लेकिन किसी भी मामले में, वास्तव में आसान है।
अनस्तासियोस एंड्रोनिडिस

आपके ऑपरेटिंग सिस्टम को फाइलसिस्टम अनुरोधों को कैश करना चाहिए ताकि यह खराब न हो :)
न्यूट्रिनस

खुद की कोशिश की, मुझे सिर्फ टाइप किया गया: असमर्थित ऑपरेंड प्रकार (ओं) के लिए -: 'सूची' और 'सूची'
टॉम बसबी

1
@TomBusby उन्हें सेट करने के लिए परिवर्तित करने का प्रयास करें: set(glob("*")) - set(glob("eph*")) (और "eph *" के अंत में सूचना दें)
Jaszczur

2
बस एक साइड नोट के रूप में, ग्लोब रिटर्न लिस्ट करता है और सेट नहीं करता है, लेकिन इस तरह का ऑपरेशन केवल सेट पर काम करता है, इसलिए न्यूट्रिनस ने इसे क्यों डाला। यदि आपको एक सूची में रहने की आवश्यकता है, तो बस एक ऑपरेशन में पूरे ऑपरेशन को लपेटें:list(set(glob("*")) - set(glob("eph")))
नाथन स्मिथ

48

आप globफ़ंक्शन के साथ पैटर्न को बाहर नहीं कर सकते , ग्लब्स केवल समावेश पैटर्न के लिए अनुमति देते हैं । ग्लोबिंग सिंटैक्स बहुत सीमित है (यहां तक ​​कि एक [!..]चरित्र वर्ग को एक चरित्र से मेल खाना चाहिए , इसलिए यह प्रत्येक वर्ण के लिए एक समावेश पैटर्न है जो कक्षा में नहीं है)।

आपको अपना फ़िल्टर करना होगा; एक सूची की समझ आमतौर पर यहाँ अच्छी तरह से काम करती है:

files = [fn for fn in glob('somepath/*.txt') 
         if not os.path.basename(fn).startswith('eph')]

3
iglobमेमोरी में पूरी सूची को स्टोर करने से बचने के लिए यहां उपयोग करें
यूजीन पैंकोव

3
@ हर्डेक्स: आंतरिक रूप से, वैसे भीiglob सूचियों का उत्पादन करता है ; आप सभी आलसी फ़िल्टर का मूल्यांकन करते हैं। यह स्मृति पदचिह्न को कम करने में मदद नहीं करेगा।
मार्टिन पीटर्स

@ हर्डेक्स: यदि आप निर्देशिका नाम में एक ग्लोब का उपयोग करते हैं , तो आपके पास एक बिंदु होगा, तो अधिकतम os.listdir()परिणाम में स्मृति में रखा जाता है जैसे कि आप इसे पुनरावृत्त करते हैं। लेकिन somepath/*.txtसभी फ़ाइलनामों को एक निर्देशिका में मेमोरी में पढ़ना होगा, फिर उस सूची को केवल उस मैच तक कम करें।
मार्टिन पीटर्स

तुम सही हो, यह महत्वपूर्ण है कि नहीं है, लेकिन शेयर CPython में, glob.glob(x) = list(glob.iglob(x))। अधिक उपरि नहीं, लेकिन फिर भी अच्छा है।
यूजीन पानकोव

यह पुनरावृति दो बार नहीं करता है ?. एक बार सूची प्राप्त करने के लिए फ़ाइलों के माध्यम से और दूसरी सूची के माध्यम से ही? यदि हां, तो क्या इसे एक पुनरावृत्ति में करना संभव नहीं है?
रिधुदर्शन

6

खेल के लिए देर से लेकिन आप वैकल्पिक रूप filterसे एक परिणाम के लिए एक अजगर लागू कर सकते हैं glob:

files = glob.iglob('your_path_here')
files_i_care_about = filter(lambda x: not x.startswith("eph"), files)

या एक उचित रेगेक्स खोज, आदि के साथ लैम्ब्डा की जगह ...

संपादित करें: मुझे बस एहसास हुआ कि यदि आप पूर्ण पथों का उपयोग नहीं कर रहे हैं startswith, तो आपको एक regex की आवश्यकता होगी

In [10]: a
Out[10]: ['/some/path/foo', 'some/path/bar', 'some/path/eph_thing']

In [11]: filter(lambda x: not re.search('/eph', x), a)
Out[11]: ['/some/path/foo', 'some/path/bar']

5

कैसे फ़ोल्डर में सभी फ़ाइलों पर पुनरावृत्ति करते समय विशेष फ़ाइल लंघन के बारे में! नीचे दिया गया कोड सभी एक्सेल फ़ाइलों को छोड़ देगा जो 'eph' से शुरू होती हैं।

import glob
import re
for file in glob.glob('*.xlsx'):
    if re.match('eph.*\.xlsx',file):
        continue
    else:
        #do your stuff here
        print(file)

इस तरह आप एक फ़ोल्डर में फ़ाइलों के एक विशेष सेट को शामिल / बाहर करने के लिए अधिक जटिल रीगेक्स पैटर्न का उपयोग कर सकते हैं।


5

के साथ तुलना करें glob, मैं सुझाता हूं pathlib, एक पैटर्न को फ़िल्टर करना बहुत सरल है।

from pathlib import Path

p = Path(YOUR_PATH)
filtered = [x for x in p.glob("**/*") if not x.name.startswith("eph")]

और यदि आप अधिक जटिल पैटर्न को फ़िल्टर करना चाहते हैं, तो आप ऐसा करने के लिए एक फ़ंक्शन को परिभाषित कर सकते हैं, जैसे:

def not_in_pattern(x):
    return (not x.name.startswith("eph")) and not x.name.startswith("epi")


filtered = [x for x in p.glob("**/*") if not_in_pattern(x)]

उस कोड का उपयोग करें, आप उन सभी फ़ाइलों को फ़िल्टर कर सकते हैं जो शुरू होती हैं ephया जिनके साथ शुरू होती हैं epi


4

आम तौर पर, उन फ़ाइलों को बाहर करने के लिए जो कुछ शेल रीजैक्सप का अनुपालन नहीं करते हैं, आप मॉड्यूल का उपयोग कर सकते हैं fnmatch:

import fnmatch

file_list = glob('somepath')    
for ind, ii in enumerate(file_list):
    if not fnmatch.fnmatch(ii, 'bash_regexp_with_exclude'):
        file_list.pop(ind)

उपरोक्त पहले एक दिए गए पथ से एक सूची उत्पन्न करेगा और उन फ़ाइलों को पॉप आउट करेगा जो वांछित बाधा के साथ नियमित अभिव्यक्ति को संतुष्ट नहीं करेंगे।


यह स्वीकृत उत्तर होना चाहिए।
फिलिप रेमी

0

जैसा कि स्वीकृत उत्तर द्वारा बताया गया है, आप ग्लोब के साथ पैटर्न को बाहर नहीं कर सकते हैं, इसलिए निम्न आपके ग्लोब परिणाम को फ़िल्टर करने की एक विधि है।

स्वीकृत उत्तर चीजों को करने के लिए शायद सबसे अच्छा पायथोनिक तरीका है, लेकिन अगर आपको लगता है कि सूची की समझ थोड़ी बदसूरत है और अपने कोड को अधिकतम रूप से संख्यात्मक रूप से बनाना चाहते हैं (जैसे मैंने किया) तो आप ऐसा कर सकते हैं (लेकिन ध्यान दें कि यह शायद कम कुशल है सूची समझने की विधि से):

import glob

data_files = glob.glob("path_to_files/*.fits")

light_files = np.setdiff1d( data_files, glob.glob("*BIAS*"))
light_files = np.setdiff1d(light_files, glob.glob("*FLAT*"))

(मेरे मामले में, मेरे पास कुछ छवि फ़्रेम, पूर्वाग्रह फ़्रेम, और फ्लैट फ़्रेम सभी एक निर्देशिका में थे और मुझे बस छवि फ़्रेम चाहिए था)


0

यदि चरित्र की स्थिति महत्वपूर्ण नहीं है, तो यह उदाहरण के लिए है कि मैनिफ़ेस्ट फ़ाइल (जहाँ भी यह पाया जाता है _) को बाहर करना globऔर re- नियमित अभिव्यक्ति संचालन के साथ , आप उपयोग कर सकते हैं:

import glob
import re
for file in glob.glob('*.txt'):
    if re.match(r'.*\_.*', file):
        continue
    else:
        print(file)

या अधिक सुरुचिपूर्ण तरीके से - list comprehension

filtered = [f for f in glob.glob('*.txt') if not re.match(r'.*\_.*', f)]

for mach in filtered:
    print(mach)

-1

आप नीचे दी गई विधि का उपयोग कर सकते हैं:

# Get all the files
allFiles = glob.glob("*")
# Files starting with eph
ephFiles = glob.glob("eph*")
# Files which doesnt start with eph
noephFiles = []
for file in allFiles:
    if file not in ephFiles:
        noephFiles.append(file)
# noepchFiles has all the file which doesnt start with eph.

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