【问题标题】:How to glob two patterns with pathlib?如何使用 pathlib 实现两种模式?
【发布时间】:2018-06-19 05:58:00
【问题描述】:

我想找到具有两个不同扩展名的两种类型的文件:.jl.jsonlines。我用

from pathlib import Path
p1 = Path("/path/to/dir").joinpath().glob("*.jl")
p2 = Path("/path/to/dir").joinpath().glob("*.jsonlines")

但我希望 p1p2 作为一个变量而不是两个变量。我应该首先合并p1p2 吗?还有其他方法可以连接 glob 的模式吗?

【问题讨论】:

标签: python pathlib


【解决方案1】:

根据您的应用程序,建议的解决方案可能效率低下,因为它必须多次循环目录中的所有文件(每个扩展名/模式一个)。

在您的示例中,您只匹配一个文件夹中的扩展名,一个简单的解决方案可能是:

from pathlib import Path

folder = Path("/path/to/dir")
extensions = {".jl", ".jsonlines"}
files = [file for file in folder.iterdir() if file.suffix in extensions]

如果你经常使用它可以在一个函数中打开它。

但是,如果您希望能够匹配 glob 模式而不是扩展名,则应使用 match() 方法:

from pathlib import Path

folder = Path("/path/to/dir")
patterns = ("*.jl", "*.jsonlines")

files = [f for f in folder.iterdir() if any(f.match(p) for p in patterns)]

最后一个既方便又高效。您可以通过将最常见的模式放在模式列表的开头来提高效率,因为any 是一个短路运算符。

【讨论】:

  • 在我的测试中,而不是if any(f.match(p) for p in patterns,使用if f.suffix.lower() in patterns快得多,并且我将模式设置为一组。我正在测试 8 个扩展,以递归方式搜索数千个文件。
  • 是的,这是我写的第一个例子。这可能更快,因为匹配使用反射比与后缀的基本字符串比较慢得多。
【解决方案2】:

如果您可以安装软件包,请查看wcmatch。它可以修补 Python PathLib,以便您可以一次运行多个匹配项:

from wcmatch.pathlib import Path
paths = Path('path/to/dir').glob(['*.jl', '*.jsonlines'])

【讨论】:

  • 如何修改它以在所有子目录中递归搜索?
  • .glob 替换为.rglob(递归全局的缩写)
【解决方案3】:
from pathlib import Path

exts = [".jl", ".jsonlines"]
mainpath = "/path/to/dir"

# Same directory

files = [p for p in Path(mainpath).iterdir() if p.suffix in exts]

# Recursive

files = [p for p in Path(mainpath).rglob('*') if p.suffix in exts]

# 'files' will be a generator of Path objects, to unpack into strings:

list(files)

【讨论】:

  • pathlib suffix的精彩运用
【解决方案4】:

受@aditi 回答的启发,我想出了这个:

from pathlib import Path
from itertools import chain

exts = ["*.jl", "*.jsonlines"]
mainpath = "/path/to/dir"

P = []
for i in exts:
    p = Path(mainpath).joinpath().glob(i)
    P = chain(P, p)
print(list(P))

【讨论】:

    【解决方案5】:

    试试这个:

    from os.path import join
    from glob import glob
    
    files = []
    for ext in ('*.jl', '*.jsonlines'):
       files.extend(glob(join("path/to/dir", ext)))
    
    print(files)
    

    【讨论】:

    • 谢谢@aditi。我编辑了我的问题,因为来自itertoolschain 也可以。在将它们与chain 连接之前,我已经使用了p1p2。您的回答也是一个很好且直接的解决方案。
    • 有没有使用pathlibPath的解决方案?
    • 试试这个:from pathlib import Path def get_files(extensions): all_files = [] for ext in extensions: all_files.extend(Path('.').glob(ext)) return all_files files = get_files(('*.jl', '*.jsonlines'))
    • 好!但它会将生成器更改为列出占用内存过多的生成器。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-06-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多