Python os.walk/fnmatch.filter 在文件的当前目录中找不到文件

Python os.walk/fnmatch.filter does not find file when in file's current directory

我正在尝试递归遍历目录并查找与特定模式匹配的文件。我的代码的相关片段是:

import sys, os, xlrd, fnmatch

for root, dirnames, filenames in os.walk('/myfilepath/'):

    for dir in dirnames:
        os.chdir(os.path.join(root, dir))

        for filename in fnmatch.filter(filenames, 'filepattern*'):
            print os.path.abspath(filename)
            print os.getcwd()
            print filename

            wb = xlrd.open_workbook(filename)

我的打印行表明 os.getcwd() 等于文件名的目录,所以对我来说似乎应该找到该文件,但是 IOError: [Errno 2] No such file or directory 被抛出 wb = xlrd.open_workbook(filename) 当第一个模式匹配。

来自 os.walkdirnames return 不代表 filenames 所在的目录。相反,root 表示 filenames 所在的目录。对于您的应用程序,您可以有效地忽略 directories return.

尝试这样的事情:

import os
import fnmatch

for root, _, filenames in os.walk('/tmp'):
    print root, filenames
    for filename in fnmatch.filter(filenames, '*.py'):
        filename = os.path.join(root, filename)

        # `filename` now unambiguously refers to a file that
        # exists. Open it, delete it, xlrd.open it, whatever.
        # For example:
        if os.access(filename, os.R_OK):
            print "%s can be accessed"  % filename
        else:
            print "%s cannot be accessed"  % filename

旁白:在os.walk() 迭代中调用os.chdir() 可能不安全。如果 os.walk() 的参数是相对的,则尤其如此。

喜欢linux在Python中找到? 存在更强大的文件查找技术,使用 glob 类似于 Linux find 并且它使用非常强大的 pathlib 来处理不同格式的路径。

适用于 Python 3.5 或更高版本,我使用的是版本 3.7,它适用于旧 mac、友好 [=7​​4=] 甚至间谍 Windows 10。

清晰示例(不允许使用部分代码片段)。

import glob
import subprocess
from pathlib import PurePath

    # Return a list of matching files
    def find_files(start_dir, pattern, recurse=True):
        patt = start_dir.strip() + '/**/' + pattern
        files = []
        for f in glob.iglob(patt, recursive=recurse):
            files.append(PurePath(f))
        return files

recurseTrue 时,它会在当前目录和子目录中找到与模式匹配的文件。 当recurse为False时,只搜索本地当前目录。

glob.iglob() 是 glob.glob() 的迭代器版本,两者输出相同,除了迭代器版本在需要之前不会累积结果。

在 git 项目中使用 Python

搜索源文件的使用示例
cmd = ['git', 'rev-parse', '--show-toplevel']

result = subprocess.run(cmd, stdout=subprocess.PIPE)
gitroot = result.stdout.decode('utf-8')

print(gitroot)

ret = find_files(gitroot, "os.c")
print(ret)

找到 git 项目的 git 根,然后从那里搜索 os.c 或您喜欢的任何模式。

是的,它执行了 git 命令:

git rev-parse --show-toplevel

这很强大,这意味着您可以搜索文件并对其进行操作。 希望有所帮助 - 查看输出并注意混合的路径格式。 那是因为 Windows 仍然是混淆的,而 Linux(Posix 标准)不是。

输出

C:\Users\me\Python37\python.exe C:/Users/me/7pych/git_find_file.py *.c
C:/Users/me/git_projects/demo

[PureWindowsPath('C:/Users/me/git_projects/demo/device/src/os/os.c')]

Process finished with exit code 0

要获取仅路径名仅获取文件名称,请使用split() .看这个例子: cross-platform splitting of path in python