有没有更好的方法来使用glob。Glob在python中获取多个文件类型的列表,如.txt, .mdown和.markdown?现在我有这样的东西:

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

当前回答

不是glob,这里是另一种使用列表理解的方式:

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

其他回答

一句话:

img_ext = (".jpg", ".jpeg", ".jpeg", "。就是“,”。jfi”、“.jif”、“jpg”)

目录= './'

files = [glob.glob(目录+'/*')中的文件的文件if file.endswith(img_ext)]

根据我从经验测试中得到的结果,那一团东西。Glob并不是通过扩展名过滤文件的更好方法。其中一些原因是:

通配符“语言”不允许对多个扩展进行完美的规范。 前一点导致根据文件扩展名获得不正确的结果。 经经验证明,通配符法比大多数其他方法都要慢。 即使这很奇怪,甚至其他文件系统对象也可以有“扩展名”,文件夹也是如此。

我已经测试了以下4种不同的方法,通过扩展名过滤文件,并将它们放在一个列表中:

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.

通过扩展名过滤文件的最快方法,甚至是最丑陋的方法。也就是说,使用endswith()方法进行嵌套for循环和字符串比较。

此外,正如您所看到的,配色算法(使用模式E:\x\y\z\**/*[py][pyc])即使只给出两个扩展名(py和pyc)也会返回不正确的结果。

以下是Pat回答的一行列表理解变体(其中还包括您想要在特定的项目目录中glob):

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

循环遍历扩展名(对于extts中的ext),然后对于每个扩展名,使用匹配glob模式的每个文件(对于glob.glob中的f (os.path. path))。加入(project_dir ext))。

这个解决方案很短,没有任何不必要的for循环、嵌套的列表推导式或使代码混乱的函数。纯粹的,富有表现力的,蟒蛇式的禅宗。

这个解决方案允许您拥有一个自定义的文本列表,可以在不更新代码的情况下进行更改。(这是一个很好的实践!)

在Laurent的解决方案中使用了同样的列表理解(我投票支持)。但我认为,通常没有必要将单行分解为单独的函数,这就是为什么我提供这个作为替代解决方案的原因。

奖金:

如果你不仅需要搜索单个目录,还需要搜索所有子目录,你可以传递递归=True并使用多目录glob符号** 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)等等。

从技术上讲,** glob符号只是匹配一个或多个字符,包括正斜杠/(不像单数的* glob符号)。在实践中,您只需要记住,只要用斜杠(路径分隔符)包围**,它就可以匹配0个或多个目录。

也许有更好的办法,但是:

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

也许还有其他的方法,所以等待别人提出更好的答案。

您可以尝试制作一个手动列表,将现有扩展与所需扩展进行比较。

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)