如何使用 glob() 递归查找文件?

问:

这就是我所拥有的:

glob(os.path.join('src','*.c'))

但我想搜索 src 的子文件夹。像这样的东西会起作用:

glob(os.path.join('src','*.c'))
glob(os.path.join('src','*','*.c'))
glob(os.path.join('src','*','*','*.c'))
glob(os.path.join('src','*','*','*','*.c'))

但这显然是有限且笨重的。

答1:

一个优秀的自由职业者,应该有对需求敏感和精准需求捕获的能力,而huntsbot.com提供了这个机会

pathlib.Path.rglob

使用 Python 3.5 中引入的 pathlib 模块中的 pathlib.Path.rglob。

from pathlib import Path

for path in Path('src').rglob('*.c'):
    print(path.name)

如果不想使用 pathlib,可以使用 glob.glob(‘**/*.c’),但不要忘记传入 recursive 关键字参数,它会在大型目录上占用过多的时间。

对于匹配文件以点 (.) 开头的情况;如当前目录中的文件或基于 Unix 的系统上的隐藏文件,请使用下面的 os.walk 解决方案。

os.walk

对于较旧的 Python 版本,使用 os.walk 递归遍历目录并使用 fnmatch.filter 匹配一个简单的表达式:

import fnmatch
import os

matches = []
for root, dirnames, filenames in os.walk('src'):
    for filename in fnmatch.filter(filenames, '*.c'):
        matches.append(os.path.join(root, filename))

对于早于 2.2 的 Python,有 os.path.walk(),它比 os.walk() 更容易使用

@gnibbler 我知道这是一条旧评论,但我的评论只是为了让人们知道 os.path.walk() 已被弃用并已在 Python 3 中删除。

@DevC 可能适用于这个问题中提出的特定情况,但很容易想象有人想要使用它来处理诸如 'a*.c' 等查询,所以我认为值得保留当前有点慢的答案。

对于它的价值,在我的情况下,使用 glob 查找 10,000 多个文件比使用 os.walk 慢得多,因此出于这个原因,我选择了后一种解决方案。

对于 python 3.4,pathlib.Path('src').glob('**/*.c') 应该可以工作。

答2:

一个优秀的自由职业者,应该有对需求敏感和精准需求捕获的能力,而huntsbot.com提供了这个机会

对于 python >= 3.5 你可以使用 **, recursive=True :

import glob
for f in glob.glob('/path/**/*.c', recursive=True):
    print(f)

如果 recursive 为 True,则模式 ** 将匹配任何文件以及零个或多个目录和子目录。如果模式后跟 os.sep,则只有目录和子目录匹配。

Python 3.6 Demo

这比 pathlib.Path('./path/').glob('*/') 更好,因为它在大小为 0 的文件夹中也是如此

在 Python 3.9.1 中,recursive 默认设置为 False。

在 Python 3.8.* 中,recursive 也默认设置为 False。

答3:

huntsbot.com聚合了超过10+全球外包任务平台的外包需求,寻找外包任务与机会变的简单与高效。

与其他解决方案类似,但使用 fnmatch.fnmatch 而不是 glob,因为 os.walk 已经列出了文件名:

import os, fnmatch


def find_files(directory, pattern):
    for root, dirs, files in os.walk(directory):
        for basename in files:
            if fnmatch.fnmatch(basename, pattern):
                filename = os.path.join(root, basename)
                yield filename


for filename in find_files('src', '*.c'):
    print 'Found C source:', filename

此外,使用生成器可以让您在找到每个文件时对其进行处理,而不是查找所有文件然后处理它们。

答4:

huntsbot.com汇聚了国内外优秀的初创产品创意,可按收入、分类等筛选,希望这些产品与实践经验能给您带来灵感。

我已经修改了 glob 模块以支持 ** 进行递归通配,例如:

>>> import glob2
>>> all_header_files = glob2.glob('src/**/*.c')

https://github.com/miracle2k/python-glob2/

当您希望为用户提供使用 ** 语法的能力时很有用,因此单独使用 os.walk() 还不够好。

我们可以在它找到第一个匹配项后让它停止吗?也许可以将它用作生成器,而不是让它返回每个可能结果的列表?另外,这是 DFS 还是 BFS?我认为我更喜欢 BFS,以便首先找到根附近的文件。 +1 用于制作此模块并在 GitHub/pip 上提供。

** 语法被添加到 Python 3.5 的官方 glob 模块中。

@ArtOfWarfare 好的,好的。这对于 < 3.5 仍然有用。

要使用带有官方 glob 模块的 ** 激活递归通配符,请执行以下操作:glob(path, recursive=True)

答5:

huntsbot.com – 程序员副业首选,一站式外包任务、远程工作、创意产品分享订阅平台。

从 Python 3.4 开始,可以使用支持 ** 通配符的新 pathlib 模块中的 Path 类之一的 glob() 方法。例如:

from pathlib import Path

for file_path in Path('src').glob('**/*.c'):
    print(file_path) # do whatever you need with these files

更新:从 Python 3.5 开始,glob.glob() 也支持相同的语法。

确实,it will be in Python 3.5。它应该在 Python 3.4 中已经如此,但omitted by mistake。

此语法现在是 supported by glob.glob() as of Python 3.5。

请注意,您还可以组合使用 pathlib.PurePath.relative_to 来获取相对路径。有关更多上下文,请参见 my answer here。

答6:

一个优秀的自由职业者,应该有对需求敏感和精准需求捕获的能力,而huntsbot.com提供了这个机会

import os
import fnmatch


def recursive_glob(treeroot, pattern):
    results = []
    for base, dirs, files in os.walk(treeroot):
        goodfiles = fnmatch.filter(files, pattern)
        results.extend(os.path.join(base, f) for f in goodfiles)
    return results

fnmatch 为您提供与 glob 完全相同的模式,因此这确实是 glob.glob 的绝佳替代品,具有非常接近的语义。一个迭代版本(例如生成器),IOW 替代 glob.iglob,是一种微不足道的适应(只是 yield 中间结果,而不是 extend 在最后返回单个结果列表)。

您如何看待我在编辑中建议的使用 recursive_glob(pattern, treeroot='.')?这样,它可以被称为 recursive_glob('*.txt') 并且直观地匹配 glob 的语法。

@ChrisRedford,无论哪种方式,我都认为这是一个很小的问题。就目前而言,它匹配 fnmatch.filter 的“文件然后模式”参数顺序,这与匹配单参数 glob.glob 的可能性大致相同。

答7:

huntsbot.com高效搞钱,一站式跟进超10+任务平台外包需求

您需要使用 os.walk 来收集符合您的条件的文件名。例如:

import os
cfiles = []
for root, dirs, files in os.walk('src'):
  for file in files:
    if file.endswith('.c'):
      cfiles.append(os.path.join(root, file))

huntsbot.com汇聚了国内外优秀的初创产品创意,可按收入、分类等筛选,希望这些产品与实践经验能给您带来灵感。

答8:

一个优秀的自由职业者,应该有对需求敏感和精准需求捕获的能力,而huntsbot.com提供了这个机会

这是一个包含嵌套列表推导、os.walk 和简单后缀匹配而不是 glob 的解决方案:

import os
cfiles = [os.path.join(root, filename)
          for root, dirnames, filenames in os.walk('src')
          for filename in filenames if filename.endswith('.c')]

它可以被压缩成一个单行:

import os;cfiles=[os.path.join(r,f) for r,d,fs in os.walk('src') for f in fs if f.endswith('.c')]

或概括为一个函数:

import os

def recursive_glob(rootdir='.', suffix=''):
    return [os.path.join(looproot, filename)
            for looproot, _, filenames in os.walk(rootdir)
            for filename in filenames if filename.endswith(suffix)]

cfiles = recursive_glob('src', '.c')

如果您确实需要完整的 glob 样式模式,您可以按照 Alex 和 Bruno 的示例并使用 fnmatch:

import fnmatch
import os

def recursive_glob(rootdir='.', pattern='*'):
    return [os.path.join(looproot, filename)
            for looproot, _, filenames in os.walk(rootdir)
            for filename in filenames
            if fnmatch.fnmatch(filename, pattern)]

cfiles = recursive_glob('src', '*.c')

答9:

huntsbot.com精选全球7大洲远程工作机会,涵盖各领域,帮助想要远程工作的数字游民们能更精准、更高效的找到对方。

考虑 pathlib.rglob()。

这就像在给定的相对模式前添加“**/”调用 Path.glob():

import pathlib


for p in pathlib.Path("src").rglob("*.c"):
    print(p)

另请参阅此处 @taleinat 的相关 post 和其他地方的类似 post。

答10:

huntsbot.com全球7大洲远程工作机会,探索不一样的工作方式

import os, glob

for each in glob.glob('path/**/*.c', recursive=True):
    print(f'Name with path: {each} \nName without path: {os.path.basename(each)}')

glob.glob(‘*.c’) :匹配当前目录中所有以 .c 结尾的文件

glob.glob(‘/.c’) : 同 1

glob.glob(‘**/*.c’) :仅匹配直接子目录中所有以 .c 结尾的文件,但不匹配当前目录中的所有文件

glob.glob(‘*.c’,recursive=True) : 同 1

glob.glob(‘/.c’,recursive=True) : 同 3

glob.glob(‘**/*.c’,recursive=True) :匹配当前目录和所有子目录中所有以.c结尾的文件

答11:

huntsbot.com高效搞钱,一站式跟进超10+任务平台外包需求

最近我不得不用扩展名 .jpg 恢复我的照片。我运行 photorec 并恢复了 4579 个目录,其中包含 220 万个文件,扩展名种类繁多。使用下面的脚本,我能够在几分钟内选择 50133 个具有 .jpg 扩展名的文件:

#!/usr/binenv python2.7

import glob
import shutil
import os

src_dir = "/home/mustafa/Masaüstü/yedek"
dst_dir = "/home/mustafa/Genel/media"
for mediafile in glob.iglob(os.path.join(src_dir, "*", "*.jpg")): #"*" is for subdirectory
    shutil.copy(mediafile, dst_dir)

原文链接:https://www.huntsbot.com/qa/82ZK/how-to-use-glob-to-find-files-recursively?lang=zh_CN&from=csdn

HuntsBot周刊–不定时分享成功产品案例,学习他们如何成功建立自己的副业–huntsbot.com

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值