पायथन ग्लोब मल्टीपल फ़िलिपीस


142

क्या कई फ़ाइल प्रकारों जैसे .txt, .mdown और .markdown की सूची प्राप्त करने के लिए अजगर में glob.glob का उपयोग करने का एक बेहतर तरीका है? अभी मेरे पास कुछ इस तरह है:

projectFiles1 = glob.glob( os.path.join(projectDir, '*.txt') )
projectFiles2 = glob.glob( os.path.join(projectDir, '*.mdown') )
projectFiles3 = glob.glob( os.path.join(projectDir, '*.markdown') )

1
बहुत से संबंधित: stackoverflow.com/q/48181073/880783
BERS

जवाबों:


156

शायद वहाँ एक बेहतर तरीका है, लेकिन कैसे के बारे में:

import glob
types = ('*.pdf', '*.cpp') # the tuple of file types
files_grabbed = []
for files in types:
    files_grabbed.extend(glob.glob(files))

# files_grabbed is the list of pdf and cpp files

शायद एक और तरीका है, इसलिए यदि कोई और बेहतर उत्तर दे तो प्रतीक्षा करें।


19
files_grabbed = [glob.glob(e) for e in ['*.pdf', '*.cpp']]
Novitoll

10
Novitoll का समाधान कम है, लेकिन यह नेस्टेड सूचियों का निर्माण करता है।
20

9
आप हमेशा ऐसा कर सकते हैं;)[f for f_ in [glob.glob(e) for e in ('*.jpg', '*.mp4')] for f in f_]
एलेक्सजेन

1
files_grabbed = [ glob.glob (e) में e के लिए [' .pdf', '* .cpp']]
florisla

3
यह फ़ाइलों की सूची के माध्यम से दो बार लूप करता है। पहले पुनरावृत्ति में यह * .pdf के लिए जाँच करता है और दूसरे में यह * .cpp के लिए जाँच करता है। क्या इसे एक पुनरावृत्ति में लाने का कोई तरीका है? हर बार संयुक्त स्थिति की जाँच करें?
रिधुदर्शन

47
from glob import glob

files = glob('*.gif')
files.extend(glob('*.png'))
files.extend(glob('*.jpg'))

print(files)

यदि आपको एक पथ निर्दिष्ट करने की आवश्यकता है, तो मैच पैटर्न पर लूप और सादगी के लिए लूप के अंदर शामिल रहें:

from os.path import join
from glob import glob

files = []
for ext in ('*.gif', '*.png', '*.jpg'):
   files.extend(glob(join("path/to/dir", ext)))

print(files)

44

glob एक सूची देता है: क्यों न केवल इसे कई बार चलाएं और परिणामों को संक्षिप्त करें?

from glob import glob
ProjectFiles = glob('*.txt') + glob('*.mdown') + glob('*markdown')

2
यह संभवतः सबसे अधिक पठनीय समाधान है। मैं के मामले बदल जाएगा ProjectFilesकरने के लिए projectFilesहै, लेकिन महान समाधान।
हंस गोल्डमैन

40

परिणामों को चैन करें:

import itertools as it, glob

def multiple_file_types(*patterns):
    return it.chain.from_iterable(glob.iglob(pattern) for pattern in patterns)

फिर:

for filename in multiple_file_types("*.txt", "*.sql", "*.log"):
    # do stuff

13
glob.glob -> glob.iglob ताकि पुनरावृत्तियों की श्रृंखला पूरी तरह से आलसी का मूल्यांकन हो
rodrigob

1
मैं एक ही समाधान मिला, लेकिन इसके बारे में नहीं जानता था chain.from_iterable। तो यह समान है, लेकिन कम पठनीय है it.chain(*(glob.iglob(pattern) for pattern in patterns)):।
फ्लोरिसला

17

इतने सारे जवाब कि जितनी बार ग्लोबिंग करने की सलाह देते हैं, उतने विस्तार के बाद भी, मैं सिर्फ एक बार ग्लोबिंग करना पसंद करूंगा -

from pathlib import Path

files = {p.resolve() for p in Path(path).glob("**/*") if p.suffix in [".c", ".cc", ".cpp", ".hxx", ".h"]}

15

ग्लोब के साथ यह संभव नहीं है। आप केवल उपयोग कर सकते हैं:
* सब कुछ मेल खाता है
? किसी भी एक चरित्र से मेल खाता है
[seq] seq में किसी भी चरित्र से मेल खाता है
!

पैटर्न की जाँच करने के लिए os.listdir और regexp का उपयोग करें:

for x in os.listdir('.'):
  if re.match('.*\.txt|.*\.sql', x):
    print x

10
$ के साथ अपने रेगेक्स को समाप्त करने के लिए केवल फ़ाइल नाम के अंत तक मिलान करें
ThiefMaster

1
मुझे यह तरीका पसंद है - अगर ग्लोब की स्पष्टता पर्याप्त शक्तिशाली नहीं है, तो अधिक शक्तिशाली रेगेक्स सिस्टम में अपग्रेड करें, जैसे itertoolsकि इसका उपयोग करके हैक न करें क्योंकि बाद के पैटर्न में बदलाव भी हैक किए जा सकते हैं (जैसे आप ऊपरी और निचले मामले की अनुमति देना चाहते हैं) । ओह, और यह लिखने के लिए क्लीनर हो सकता है'.*\.(txt|sql)'
मेटाकेरमिट

क्या ग्लोब.इग्लोब (' ') से अधिक os.listdir ('।') को पसंद करने का कोई कारण है ?
Mr.WorshipMe

14

उदाहरण के लिए, के लिए *.mp3और *.flacअधिक फ़ोल्डर पर, आप कर सकते हैं:

mask = r'music/*/*.[mf][pl][3a]*'
glob.glob(mask)

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

एक एकल ग्लोब पैटर्न में एक्सटेंशन की मनमानी सूची को स्वचालित रूप से संयोजित करने के लिए, आप निम्न कार्य कर सकते हैं:

mask_base = r'music/*/*.'
exts = ['mp3', 'flac', 'wma']
chars = ''.join('[{}]'.format(''.join(set(c))) for c in zip(*exts))
mask = mask_base + chars + ('*' if len(set(len(e) for e in exts)) > 1 else '')
print(mask)  # music/*/*.[fmw][plm][3a]*

6

एक लाइनर, बस इसके लिए नरक ..

folder = "C:\\multi_pattern_glob_one_liner"
files = [item for sublist in [glob.glob(folder + ext) for ext in ["/*.txt", "/*.bat"]] for item in sublist]

उत्पादन:

['C:\\multi_pattern_glob_one_liner\\dummy_txt.txt', 'C:\\multi_pattern_glob_one_liner\\dummy_bat.bat']

4

मदद के लिए यहां आने के बाद, मैंने अपना समाधान बनाया और इसे साझा करना चाहता था। यह user2363986 के उत्तर पर आधारित है, लेकिन मुझे लगता है कि यह अधिक मापनीय है। मतलब, यदि आपके पास 1000 एक्सटेंशन हैं, तो कोड अभी भी कुछ हद तक सुरुचिपूर्ण दिखाई देगा।

from glob import glob

directoryPath  = "C:\\temp\\*." 
fileExtensions = [ "jpg", "jpeg", "png", "bmp", "gif" ]
listOfFiles    = []

for extension in fileExtensions:
    listOfFiles.extend( glob( directoryPath + extension ))

for file in listOfFiles:
    print(file)   # Or do other stuff

मेरे लिए काम नहीं करता है। मैं उपयोग करता हूंdirectoryPath = "/Users/bla/bla/images_dir*."
Neustack

मुझे आपके लिए इसे डीबग करने के लिए अधिक जानकारी की आवश्यकता होगी ... क्या आपको अपवाद मिल रहा है? इसके अलावा, यदि आप विंडोज पर हैं, तो वह रास्ता ऐसा नहीं लगता है कि यह काम करेगा (ड्राइव ड्राइव को याद नहीं)।
हंस गोल्डमैन


4

जबकि बैश के ग्लोब के बाद पायथन का डिफ़ॉल्ट ग्लोब वास्तव में पालन नहीं करता है, आप अन्य पुस्तकालयों के साथ ऐसा कर सकते हैं। हम wcmatch के ग्लोब में ब्रेसिज़ को सक्षम कर सकते हैं ।

>>> from wcmatch import glob
>>> glob.glob('*.{md,ini}', flags=glob.BRACE)
['LICENSE.md', 'README.md', 'tox.ini']

यदि आप अपनी प्राथमिकता के अनुसार विस्तारित ग्लोब पैटर्न का उपयोग कर सकते हैं:

from wcmatch import glob
>>> glob.glob('*.@(md|ini)', flags=glob.EXTGLOB)
['LICENSE.md', 'README.md', 'tox.ini']

यह recursiveझंडा नहीं
शामून

@Shamoon नहीं, यह लेता है glob.GLOBSTARझंडा
facelessuser

3

मैंने फॉर्मिक जारी किया है जिसमें अपाचे चींटी के फाइलसेट और ग्लब्स के समान कई तरीके लागू होते हैं ।

खोज को लागू किया जा सकता है:

import formic
patterns = ["*.txt", "*.markdown", "*.mdown"]
fileset = formic.FileSet(directory=projectDir, include=patterns)
for file_name in fileset.qualified_files():
    # Do something with file_name

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

patterns = [ "/unformatted/**/*.txt", "/formatted/**/*.mdown" ]

आशा है कि ये आपकी मदद करेगा।


3

_globकई फ़ाइल एक्सटेंशन के लिए निम्न फ़ंक्शन ग्लब्स।

import glob
import os
def _glob(path, *exts):
    """Glob for multiple file extensions

    Parameters
    ----------
    path : str
        A file name without extension, or directory name
    exts : tuple
        File extensions to glob for

    Returns
    -------
    files : list
        list of files matching extensions in exts in path

    """
    path = os.path.join(path, "*") if os.path.isdir(path) else path + "*"
    return [f for files in [glob.glob(path + ext) for ext in exts] for f in files]

files = _glob(projectDir, ".txt", ".mdown", ".markdown")

3

यह एक पायथन 3.4+ pathlibसमाधान है:

exts = ".pdf", ".doc", ".xls", ".csv", ".ppt"
filelist = (str(i) for i in map(pathlib.Path, os.listdir(src)) if i.suffix.lower() in exts and not i.stem.startswith("~"))

इसके साथ ही यह सभी फ़ाइल नामों की अनदेखी करता है ~


3

यहाँ पैट के उत्तर की एक-पंक्ति सूची-बोधगम्यता संस्करण है (जिसमें यह भी शामिल है कि आप एक विशिष्ट श्रेणी निर्देशिका में ग्लोब करना चाहते थे):

import os, glob
exts = ['*.txt', '*.mdown', '*.markdown']
files = [f for ext in exts for f in glob.glob(os.path.join(project_dir, ext))]

आप एक्सटेंशन ( for ext in exts) पर लूप करते हैं , और फिर प्रत्येक एक्सटेंशन के लिए आप ग्लोब पैटर्न से मेल खाती प्रत्येक फ़ाइल लेते हैं (for f in glob.glob(os.path.join(project_dir, ext) ) से ।

यह समाधान छोटा है , और बिना किसी अनावश्यक-लूप के, नेस्टेड सूची-समझ, या कोड को अव्यवस्थित करने के लिए कार्य करता है। बस शुद्ध, अभिव्यंजक, पायथोनिक ज़ेन

यह समाधान आपको कस्टम सूची की अनुमति देता है exts जिसे आपके कोड को अपडेट किए बिना बदला जा सकता है। (यह हमेशा एक अच्छा अभ्यास है!)

लिस्ट-कॉम्प्रिहेंशन का उपयोग लॉरेंट के समाधान में किया जाता है (जिसे मैंने वोट दिया है)। लेकिन मैं यह तर्क दूंगा कि आमतौर पर किसी एक लाइन को एक अलग फ़ंक्शन में डालना अनावश्यक है, यही वजह है कि मैं इसे वैकल्पिक समाधान के रूप में प्रदान कर रहा हूं।

बक्शीश:

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

files = [f for ext in exts 
         for f in glob.glob(os.path.join(project_dir, '**', ext), recursive=True)]

यह आह्वान करेगा glob.glob('<project_dir>/**/*.txt', recursive=True) प्रत्येक विस्तार के लिए ।

1 तकनीकी रूप से, **ग्लोब प्रतीक केवल एक या एक से अधिक अक्षरों से मेल खाता है जिसमें फॉरवर्ड-स्लैश / (एकवचन *ग्लोब प्रतीक के विपरीत ) शामिल हैं। व्यवहार में, आपको बस यह याद रखने की आवश्यकता है कि जब तक आप **फॉरवर्ड स्लैश (पथ विभाजक) से घिरे रहते हैं , यह शून्य या अधिक निर्देशिकाओं से मेल खाता है।


2

नहीं glob, लेकिन यहाँ एक सूची समझ का उपयोग करने का दूसरा तरीका है:

extensions = 'txt mdown markdown'.split()
projectFiles = [f for f in os.listdir(projectDir) 
                  if os.path.splitext(f)[1][1:] in extensions]

1

आप उन लोगों की आवश्यकता वाले मौजूदा के विस्तार की तुलना करके एक मैनुअल सूची बनाने की कोशिश कर सकते हैं।

ext_list = ['gif','jpg','jpeg','png'];
file_list = []
for file in glob.glob('*.*'):
  if file.rsplit('.',1)[1] in ext_list :
    file_list.append(file)


1

करने के लिए globकई फ़ाइल प्रकार, आप कॉल करने की आवश्यकताglob() एक पाश में समारोह कई बार। चूंकि यह फ़ंक्शन एक सूची देता है, इसलिए आपको सूचियों को संक्षिप्त करना होगा।

उदाहरण के लिए, यह कार्य कार्य करता है:

import glob
import os


def glob_filetypes(root_dir, *patterns):
    return [path
            for pattern in patterns
            for path in glob.glob(os.path.join(root_dir, pattern))]

सरल उपयोग:

project_dir = "path/to/project/dir"
for path in sorted(glob_filetypes(project_dir, '*.txt', '*.mdown', '*.markdown')):
    print(path)

आप glob.iglob()एक पुनरावृत्ति के लिए भी उपयोग कर सकते हैं :

एक पुनरावृत्तिकर्ता लौटें जो ग्लोब () के समान मूल्यों को उत्पन्न करता है, वास्तव में उन सभी को एक साथ संग्रहीत किए बिना।

def iglob_filetypes(root_dir, *patterns):
    return (path
            for pattern in patterns
            for path in glob.iglob(os.path.join(root_dir, pattern)))

1

विस्तार और पुनरावृति की सूची का उपयोग करें

from os.path import join
from glob import glob

files = []
extensions = ['*.gif', '*.png', '*.jpg']
for ext in extensions:
   files.extend(glob(join("path/to/dir", ext)))

print(files)

0

आप फ़िल्टर का उपयोग कर सकते हैं:

import os
import glob

projectFiles = filter(
    lambda x: os.path.splitext(x)[1] in [".txt", ".mdown", ".markdown"]
    glob.glob(os.path.join(projectDir, "*"))
)

0

आप भी इस reduce()तरह का उपयोग कर सकते हैं :

import glob
file_types = ['*.txt', '*.mdown', '*.markdown']
project_files = reduce(lambda list1, list2: list1 + list2, (glob.glob(t) for t in file_types))

यह glob.glob()प्रत्येक पैटर्न के लिए एक सूची बनाता है और उन्हें एक सूची में घटाता है।


0

एक ग्लोब, कई एक्सटेंशन ... लेकिन अपूर्ण समाधान (अन्य फ़ाइलों से मेल खा सकता है)।

filetypes = ['tif', 'jpg']

filetypes = zip(*[list(ft) for ft in filetypes])
filetypes = ["".join(ch) for ch in filetypes]
filetypes = ["[%s]" % ch for ch in filetypes]
filetypes = "".join(filetypes) + "*"
print(filetypes)
# => [tj][ip][fg]*

glob.glob("/path/to/*.%s" % filetypes)

0

मेरे पास एक ही मुद्दा था और यही वह है जिसके साथ मैं आया था

import os, sys, re

#without glob

src_dir = '/mnt/mypics/'
src_pics = []
ext = re.compile('.*\.(|{}|)$'.format('|'.join(['png', 'jpeg', 'jpg']).encode('utf-8')))
for root, dirnames, filenames in os.walk(src_dir):
  for filename in filter(lambda name:ext.search(name),filenames):
    src_pics.append(os.path.join(root, filename))

0

फिर भी एक अन्य समाधान ( globकई मैच का उपयोग करके पथ प्राप्त करने के लिए patternsऔर सभी रास्तों को एक ही सूची में जोड़कर reduceऔर उपयोग करके add):

import functools, glob, operator
paths = functools.reduce(operator.add, [glob.glob(pattern) for pattern in [
    "path1/*.ext1",
    "path2/*.ext2"]])

0

यदि आप इसका उपयोग pathlibकरते हैं तो कोशिश करें:

import pathlib

extensions = ['.py', '.txt']
root_dir = './test/'

files = filter(lambda p: p.suffix in extensions, pathlib.Path(root_dir).glob('**/*'))

print(list(files))

0

अनुभवजन्य परीक्षणों से मुझे जो परिणाम मिले हैं, उनके नतीजों glob.globसे फाइलों को फ़िल्टर करने का बेहतर तरीका नहीं निकला । कुछ कारण हैं:

  • ग्लोबिंग " भाषा " कई विस्तार के सही विनिर्देश की अनुमति नहीं देता है।
  • पूर्व बिंदु फ़ाइल एक्सटेंशन के आधार पर गलत परिणाम प्राप्त करता है।
  • ग्लोबिंग विधि अनुभवजन्य रूप से अन्य विधियों की तुलना में धीमी साबित होती है।
  • यहां तक ​​कि अगर यह अजीब है यहां तक ​​कि अन्य फाइल सिस्टम ऑब्जेक्ट में " एक्सटेंशन ", फ़ोल्डर्स भी हो सकते हैं।

मैंने परीक्षण किया है (समय में शुद्धता और दक्षता के लिए) 4एक्सटेंशन द्वारा फ़ाइलों को फ़िल्टर करने के लिए निम्नलिखित विभिन्न विधियाँ और उन्हें एक में रखता है list:

from glob import glob, iglob
from re import compile, findall
from os import walk


def glob_with_storage(args):

    elements = ''.join([f'[{i}]' for i in args.extensions])
    globs = f'{args.target}/**/*{elements}'
    results = glob(globs, recursive=True)

    return results


def glob_with_iteration(args):

    elements = ''.join([f'[{i}]' for i in args.extensions])
    globs = f'{args.target}/**/*{elements}'
    results = [i for i in iglob(globs, recursive=True)]

    return results


def walk_with_suffixes(args):

    results = []
    for r, d, f in walk(args.target):
        for ff in f:
            for e in args.extensions:
                if ff.endswith(e):
                    results.append(path_join(r,ff))
                    break
    return results


def walk_with_regs(args):

    reg = compile('|'.join([f'{i}$' for i in args.extensions]))

    results = []
    for r, d, f in walk(args.target):
        for ff in f:
            if len(findall(reg,ff)):
                results.append(path_join(r, ff))

    return results

अपने लैपटॉप पर ऊपर दिए गए कोड को चलाकर मैंने निम्नलिखित ऑटो-खोजी परिणाम प्राप्त किए।

Elapsed time for '7 times glob_with_storage()':  0.365023 seconds.
mean   : 0.05214614
median : 0.051861
stdev  : 0.001492152
min    : 0.050864
max    : 0.054853

Elapsed time for '7 times glob_with_iteration()':  0.360037 seconds.
mean   : 0.05143386
median : 0.050864
stdev  : 0.0007847381
min    : 0.050864
max    : 0.052859

Elapsed time for '7 times walk_with_suffixes()':  0.26529 seconds.
mean   : 0.03789857
median : 0.037899
stdev  : 0.0005759071
min    : 0.036901
max    : 0.038896

Elapsed time for '7 times walk_with_regs()':  0.290223 seconds.
mean   : 0.04146043
median : 0.040891
stdev  : 0.0007846776
min    : 0.04089
max    : 0.042885

Results sizes:
0 2451
1 2451
2 2446
3 2446

Differences between glob() and walk():
0 E:\x\y\z\venv\lib\python3.7\site-packages\Cython\Includes\numpy
1 E:\x\y\z\venv\lib\python3.7\site-packages\Cython\Utility\CppSupport.cpp
2 E:\x\y\z\venv\lib\python3.7\site-packages\future\moves\xmlrpc
3 E:\x\y\z\venv\lib\python3.7\site-packages\Cython\Includes\libcpp
4 E:\x\y\z\venv\lib\python3.7\site-packages\future\backports\xmlrpc

Elapsed time for 'main':  1.317424 seconds.

एक्सटेंशन द्वारा फ़ाइलों को फ़िल्टर करने का सबसे तेज़ तरीका, यहां तक ​​कि सबसे बदसूरत होना भी है। जो है, नेस्टेड forलूप और विधि stringका उपयोग करके तुलना endswith()

इसके अलावा, जैसा कि आप देख सकते हैं, ग्लोबिंग एल्गोरिदम (पैटर्न के E:\x\y\z\**/*[py][pyc]साथ) यहां तक ​​कि केवल 2दिए गए एक्सटेंशन ( pyऔर pyc) के साथ भी गलत परिणाम मिलते हैं।


0
import glob
import pandas as pd

df1 = pd.DataFrame(columns=['A'])
for i in glob.glob('C:\dir\path\*.txt'):
    df1 = df1.append({'A': i}, ignore_index=True)
for i in glob.glob('C:\dir\path\*.mdown'):
    df1 = df1.append({'A': i}, ignore_index=True)
for i in glob.glob('C:\dir\path\*.markdown):
    df1 = df1.append({'A': i}, ignore_index=True)

हाय स्व वू, आपका स्वागत है। कृपया स्पष्टीकरण जोड़ने पर विचार करें।
टियागो मार्टिंस पेर

-1

यह काम करना चाहिए:

import glob
extensions = ('*.txt', '*.mdown', '*.markdown')
for i in extensions:
    for files in glob.glob(i):
        print (files)

-1

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

import glob
lst_img = []
base_dir = '/home/xy/img/'

# get all the jpg file in base_dir 
lst_img += glob.glob(base_dir + '*.jpg')
print lst_img
# ['/home/xy/img/2.jpg', '/home/xy/img/1.jpg']

# append all the png file in base_dir to lst_img
lst_img += glob.glob(base_dir + '*.png')
print lst_img
# ['/home/xy/img/2.jpg', '/home/xy/img/1.jpg', '/home/xy/img/3.png']

एक समारोह:

import glob
def get_files(base_dir='/home/xy/img/', lst_extension=['*.jpg', '*.png']):
    """
    :param base_dir:base directory
    :param lst_extension:lst_extension: list like ['*.jpg', '*.png', ...]
    :return:file lists like ['/home/xy/img/2.jpg','/home/xy/img/3.png']
    """
    lst_files = []
    for ext in lst_extension:
        lst_files += glob.glob(base_dir+ext)
    return lst_files
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.