1

我有这个脚本,我毫不怀疑它是有缺陷的:

import fnmatch, os, sys
def findit (rootdir, find, pattern):
    for folder, dirs, files in os.walk(rootdir):
        print (folder)
    for filename in fnmatch.filter(files,pattern):          
        with open(filename) as f:
            s = f.read()
            f.close()
            if find in s :                  
                print(filename)

findit(sys.argv[1], sys.argv[2], sys.argv[3])

当我运行它时,我得到Errno2, no such file or directory. 但是该文件存在。例如,如果我通过 go 执行它:findit.py c:\python "folder" *.py它会正常工作,列出所有包含“文件夹”一词的 *.py 文件。但是如果我去findit.py c:\php\projects1 "include" *.php

作为一个例子,我得到[Errno2] no such file or directory: 'About.php'(例如)。但是 About.php 存在。我不明白它在做什么,或者我做错了什么。

4

2 回答 2

2

如果您查看 的任何示例os.walk,您会发现它们都可以os.path.join(root, name)。你也需要这样做。

为什么?引用文档:

filenames是 dirpath 中非目录文件的名称列表。请注意,列表中的名称不包含路径组件。要获取 dirpath 中文件或目录的完整路径(以 top 开头),请执行os.path.join(dirpath, name).

如果只使用文件名作为路径,它将在当前工作目录中查找同名文件。如果没有这样的文件,你会得到一个FileNotFoundError. 如果有这样的文件,您将打开并读取错误的文件。只有当您碰巧正在查看当前工作目录时,它才会起作用。


您的代码中还有另一个主要问题:os.walk递归遍历目录树,查找给定top目录中的所有文件,或 的任何子目录top,或...的任何子目录,依此类推,为每个目录产生一次。但是你没有做任何有用的事情(除了打印出文件夹)。相反,您等到它完成,然后使用files它碰巧最后到达的目录。

如果您只想直接在目录中获取文件的平面列表,请使用os.listdir,而不是os.walk. (或者也许使用glob.glob而不是显式列出所有内容然后使用过滤fnmatch。)

另一方面,如果您想在树上行走,则必须将第二个循环移到for第一个循环内。


您还有一个小问题:您f.close()在 a 内部调用with open(…) as f:,这导致f被关闭两次。这保证是完全无害的(至少在 2.5+ 中,包括 3.x),但这仍然是一个坏主意。


放在一起,这是您的代码的工作版本:

def findit (rootdir, find, pattern):
    for folder, dirs, files in os.walk(rootdir):
        print (folder)
        for filename in fnmatch.filter(files,pattern):
            pathname = os.path.join(folder, filename)
            with open(pathname) as f:
                s = f.read()
                if find in s:
                    print(pathname)
于 2013-04-03T23:43:10.097 回答
1

您正在使用相对文件名。但是您的当前目录不包含该文件。而且你也不想在那里搜索。使用 os.path.join(folder, filename) 创建绝对路径。

于 2013-04-03T23:36:15.160 回答