我有这个脚本,我毫无疑问是有缺陷的:
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
。但该文件存在。例如,如果我执行它:findit.py c:\python "folder" *.py
它将正常工作,列出包含单词“folder”的所有* .py文件。但是如果我去findit.py c:\php\projects1 "include" *.php
作为示例,我得到[Errno2] no such file or directory: 'About.php'
(例如)。但是About.php存在。我不明白它在做什么,或者我做错了什么。
答案 0 :(得分: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()
内拨打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)
答案 1 :(得分:1)
您正在使用相对文件名。但是您当前的目录不包含该文件。而且你不想在那里搜索。使用os.path.join(文件夹,文件名)来创建绝对路径。