我有一个带有csv文件的目录树,我希望按照这种模式返回文件(模式来自其他地方,所以我需要坚持下去):
"foo"
应与foo/**/*.csv
和/或 foo.csv
匹配,以便
"foo/bar"
匹配,例如foo/bar.csv
,foo/bar/baz.csv
和foo/bar/baz/qux.csv
到目前为止,我已经两次iterating through目录树了;首先查找文件,然后查找目录:
from glob import iglob
from itertools import chain
import os
path = "csv_dir"
pattern = "foo/bar"
pattern = os.path.join(*pattern.split("/"))
path_with_pattern = os.path.join(path, pattern)
# first get all csv files in foo/bar and subdirs
files_1 = chain.from_iterable(iglob(os.path.join(root, '*.csv'))
for root, dirs, files in os.walk(path_with_pattern))
# then get all foo/bar.csv files
files_2 = chain.from_iterable(iglob(os.path.join(root, pattern + '.csv'))
for root, dirs, files in os.walk(path))
for f in chain(files_1, files_2):
print(f)
这样可行,但迭代树两次感觉很愚蠢。我错过了一个聪明的文件匹配方法吗?或者,如果我从树中获取所有csv文件开始过滤它们的简单方法呢?
答案 0 :(得分:1)
如果您可以使用不同的库,我建议使用正则表达式,因为我发现它们在遍历目录以查找特定文件和目录命名模式时非常有用。
如果不熟悉正则表达式,这里有一些信息。
关于正则表达式的Python文档:https://docs.python.org/2/library/re.html
正则表达式工具测试(效果很好,虽然它说它适用于Ruby):http://rubular.com/
import os
import re
def searchDirectory(cwd,searchParam,searchResults):
dirs = os.listdir(cwd)
for dir in dirs:
fullpath = os.path.join(cwd,dir)
if os.path.isdir(fullpath):
searchDirectory(fullpath,searchParam,searchResults)
if re.search(searchParam,fullpath):
searchResults.append(fullpath)
当且仅当当前项是另一个目录时,该函数将遍历目录的内容并进行递归调用。之后,它将在当前项的路径上执行正则表达式搜索。它只会一次访问目录中的项目。
为了简单起见,我将路径存储在列表中,但您可以更改使用这些路径执行的操作。这可以在if语句中检查正则表达式匹配。
if re.search(searchParam,fullpath):
searchResults.append(fullpath)
我使用一个小测试目录运行下面的代码。
searchParam = r'(foo\\bar\\.*\.txt|foo\\.*bar\.txt)'
root = os.getcwd();
searchResults = [];
searchDirectory(root,searchParam,searchResults)
print searchResults
跑步后的结果:
<homePath>\foo\bar\baz.txt
<homePath>\foo\bar\biz\qua.txt
<homePath>\foo\bar.txt
<homePath>\foo\baz\bar.txt
作为一个注释,我使用的是Python 2.7和Anaconda发行版。
编辑:我使用文本文件快速创建目录,但是如果你在正则表达式中更改扩展名,它仍然有效。