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

时间:2015-09-23 17:56:20

标签: python io os.walk

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

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)模式匹配。

2 个答案:

答案 0 :(得分:2)

dirnames返回的os.walk代表filenames存在的目录。相反,root表示filenames存在的目录。对于您的应用程序,您可以有效地忽略directories返回。

尝试这样的事情:

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.chdir()次迭代中调用os.walk()可能不安全。如果os.walk()的参数是相对的,则尤其如此。

答案 1 :(得分:0)

,就像Linux在Python中一样? 存在一种更强大的查找文件的技术,使用 glob 就像Linux的find一样,它使用功能非常强大的 pathlib 处理不同格式的路径。

适用于Python 3.5或更高版本,我使用的是3.7版,它可在旧的Mac,友好的Linux甚至间谍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

recurse True 时,它将在当前目录和子目录中找到与模式匹配的文件。 当递归为 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