有没有更好的方法在python中使用glob.glob来获取多种文件类型的列表,如.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') )
Run Code Online (Sandbox Code Playgroud)
use*_*312 128
也许有更好的方法,但如何:
>>> import glob
>>> types = ('*.pdf', '*.cpp') # the tuple of file types
>>> files_grabbed = []
>>> for files in types:
... files_grabbed.extend(glob.glob(files))
...
>>> files_grabbed # the list of pdf and cpp files
Run Code Online (Sandbox Code Playgroud)
也许还有另一种方式,所以请等待其他人提出更好的答案.
use*_*986 40
from glob import glob
files = glob('*.gif')
files.extend(glob('*.png'))
files.extend(glob('*.jpg'))
print(files)
Run Code Online (Sandbox Code Playgroud)
如果需要指定路径,请循环匹配模式并将连接保持在循环内以简化:
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)
Run Code Online (Sandbox Code Playgroud)
tzo*_*zot 35
结果结果:
import itertools as it, glob
def multiple_file_types(*patterns):
return it.chain.from_iterable(glob.iglob(pattern) for pattern in patterns)
Run Code Online (Sandbox Code Playgroud)
然后:
for filename in multiple_file_types("*.txt", "*.sql", "*.log"):
# do stuff
Run Code Online (Sandbox Code Playgroud)
BPL*_*BPL 35
如此多的答案表明 globbing 与扩展数量一样多,我更喜欢 globbing 一次:
from pathlib import Path
files = {p.resolve() for p in Path(path).glob("**/*") if p.suffix in [".c", ".cc", ".cpp", ".hxx", ".h"]}
Run Code Online (Sandbox Code Playgroud)
pat*_*ney 31
glob
返回一个列表:为什么不多次运行它并连接结果?
from glob import glob
ProjectFiles = glob('*.txt') + glob('*.mdown') + glob('*markdown')
Run Code Online (Sandbox Code Playgroud)
Chr*_*ian 15
用glob是不可能的.你只能使用:
*匹配一切
?匹配任何单个字符
[seq]匹配seq
[!seq]中的任何字符匹配任何不在seq中的字符
使用os.listdir和regexp来检查模式:
for x in os.listdir('.'):
if re.match('.*\.txt|.*\.sql', x):
print x
Run Code Online (Sandbox Code Playgroud)
feq*_*wix 13
例如,对于*.mp3
和*.flac
在多个文件夹,你可以这样做:
mask = r'music/*/*.[mf][pl][3a]*'
glob.glob(mask)
Run Code Online (Sandbox Code Playgroud)
这个想法可以扩展到更多文件扩展名,但您必须检查这些组合是否与这些文件夹上可能存在的任何其他不需要的文件扩展名不匹配.所以,要小心这一点.
fac*_*ser 11
虽然 Python 的默认 glob 并没有真正跟随 Bash 的 glob,但您可以使用其他库来做到这一点。我们可以在wcmatch 的 glob 中启用大括号。
>>> from wcmatch import glob
>>> glob.glob('*.{md,ini}', flags=glob.BRACE)
['LICENSE.md', 'README.md', 'tox.ini']
Run Code Online (Sandbox Code Playgroud)
如果这是您的偏好,您甚至可以使用扩展的 glob 模式:
from wcmatch import glob
>>> glob.glob('*.@(md|ini)', flags=glob.EXTGLOB)
['LICENSE.md', 'README.md', 'tox.ini']
Run Code Online (Sandbox Code Playgroud)
我们可以用pathlib
; .glob
仍然不支持通配多个参数或在大括号内(如 POSIX shell 中),但我们可以轻松获得filter
结果。
例如,您可能理想地喜欢这样做:
# NOT VALID
Path(config_dir).glob("*.{ini,toml}")
# NOR IS
Path(config_dir).glob("*.ini", "*.toml")
Run Code Online (Sandbox Code Playgroud)
你可以做:
filter(lambda p: p.suffix in {".ini", ".toml"}, Path(config_dir).glob("*"))
Run Code Online (Sandbox Code Playgroud)
这还不算更糟。
这是 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))]
Run Code Online (Sandbox Code Playgroud)
您遍历扩展名 ( for ext in exts
),然后对于每个扩展名,您获取与 glob 模式 ( for f in glob.glob(os.path.join(project_dir, ext)
)匹配的每个文件。
此解决方案很短,并且没有任何不必要的 for 循环、嵌套列表推导式或使代码混乱的函数。只是纯粹的,富有表现力的,pythonic Zen。
此解决方案允许您拥有exts
可以更改的自定义列表,而无需更新您的代码。(这总是一个好习惯!)
列表理解与 Laurent 的解决方案中使用的相同(我已经投票赞成)。但我认为通常没有必要将单行分解为单独的函数,这就是为什么我提供它作为替代解决方案的原因。
奖金:
如果您不仅需要搜索单个目录,还需要搜索所有子目录,则可以传递recursive=True
并使用多目录全局符号**
1:
files = [f for ext in exts
for f in glob.glob(os.path.join(project_dir, '**', ext), recursive=True)]
Run Code Online (Sandbox Code Playgroud)
这将调用 glob.glob('<project_dir>/**/*.txt', recursive=True)
每个扩展等等。
1从技术上讲,**
glob 符号只匹配一个或多个字符,包括正斜杠 /
(与单数*
glob 符号不同)。在实践中,你只需要记住,只要你**
用正斜杠(路径分隔符)括起来,它就会匹配零个或多个目录。
单线,仅此而已..
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]
Run Code Online (Sandbox Code Playgroud)
输出:
['C:\\multi_pattern_glob_one_liner\\dummy_txt.txt', 'C:\\multi_pattern_glob_one_liner\\dummy_bat.bat']
Run Code Online (Sandbox Code Playgroud)
小智 5
files = glob.glob('*.txt')
files.extend(glob.glob('*.dat'))
Run Code Online (Sandbox Code Playgroud)
根据我从实证测试中获得的结果,事实证明这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
Run Code Online (Sandbox Code Playgroud)
通过在我的笔记本电脑上运行上面的代码,我获得了以下自动解释结果。
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.
Run Code Online (Sandbox Code Playgroud)
按扩展名过滤文件的最快方法甚至是最丑陋的方法。即,嵌套for
循环和string
比较使用的endswith()
方法。
E:\x\y\z\**/*[py][pyc]
此外,正如您所看到的,即使仅2
给出扩展名(py
和) ,通配算法(使用模式pyc
)也会返回不正确的结果。
与@BPL 相同的答案(计算效率高),但可以处理任何全局模式而不是扩展:
import os
from fnmatch import fnmatch
folder = "path/to/folder/"
patterns = ("*.txt", "*.md", "*.markdown")
files = [f.path for f in os.scandir(folder) if any(fnmatch(f, p) for p in patterns)]
Run Code Online (Sandbox Code Playgroud)
这种解决方案既高效又方便。它还与glob
(请参阅文档)的行为密切匹配。
请注意,使用内置包更简单pathlib
:
from pathlib import Path
folder = Path("/path/to/folder")
patterns = ("*.txt", "*.md", "*.markdown")
files = [f for f in folder.iterdir() if any(f.match(p) for p in patterns)]
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
103599 次 |
最近记录: |