如何在Python中使用glob.glob模块search子文件夹?
我想打开一个文件夹中的一系列子文件夹,并find一些文本文件,并打印文本文件的一些行。 我正在使用这个:
configfiles = glob.glob('C:/Users/sam/Desktop/file1/*.txt')
但是这也不能访问子文件夹。 有谁知道我可以如何使用相同的命令来访问子文件夹?
在Python 3.5和更新的版本中,使用新的recursion**/
function:
configfiles = glob.glob('C:/Users/sam/Desktop/file1/**/*.txt', recursive=True)
当设置recursive
, **
后跟一个path分隔符匹配0个或多个子目录。
在较早的Python版本中, glob.glob()
不能recursion地列出子目录中的文件。
在这种情况下,我会使用os.walk()
与fnmatch.filter()
相结合:
import os import fnmatch path = 'C:/Users/sam/Desktop/file1' configfiles = [os.path.join(dirpath, f) for dirpath, dirnames, files in os.walk(path) for f in fnmatch.filter(files, '*.txt')]
这将recursion地遍历您的目录,并返回所有绝对path名匹配的.txt
文件。 在这个特定的情况下, fnmatch.filter()
可能是矫枉过正的,你也可以使用.endswith()
testing:
import os path = 'C:/Users/sam/Desktop/file1' configfiles = [os.path.join(dirpath, f) for dirpath, dirnames, files in os.walk(path) for f in files if f.endswith('.txt')]
glob2包支持通配符,速度相当快
code = ''' import glob2 glob2.glob("files/*/**") ''' timeit.timeit(code, number=1)
在我的笔记本电脑上,大约需要2秒来匹配> 60,000个文件path 。
要查找直接子目录中的文件,请执行以下操作:
configfiles = glob.glob(r'C:\Users\sam\Desktop\*\*.txt')
对于遍历所有子目录的recursion版本,您可以使用**
并从Python 3.5开始传递recursive=True
:
configfiles = glob.glob(r'C:\Users\sam\Desktop\**\*.txt', recursive=True)
这两个函数调用返回列表。 你可以使用glob.iglob()
来逐一返回path。 或者使用pathlib
:
from pathlib import Path path = Path(r'C:\Users\sam\Desktop') txt_files_only_subdirs = path.glob('*/*.txt') txt_files_all_recursively = path.rglob('*.txt') # including the current dir
这两个方法都会返回迭代器(您可以逐个获取path)。
你可以使用Formic Python 2.6
import formic fileset = formic.FileSet(include="**/*.txt", directory="C:/Users/sam/Desktop/")
披露 – 我是这个软件包的作者。
这是一个修改后的版本,可以在不使用glob2
情况下启用glob.glob
类似的function。
def find_files(directory, pattern='*'): if not os.path.exists(directory): raise ValueError("Directory not found {}".format(directory)) matches = [] for root, dirnames, filenames in os.walk(directory): for filename in filenames: full_path = os.path.join(root, filename) if fnmatch.filter([full_path], pattern): matches.append(os.path.join(root, filename)) return matches
所以,如果你有以下的目录结构
tests/files ├── a0 │ ├── a0.txt │ ├── a0.yaml │ └── b0 │ ├── b0.yaml │ └── b00.yaml └── a1
你可以做这样的事情
files = utils.find_files('tests/files','**/b0/b*.yaml') > ['tests/files/a0/b0/b0.yaml', 'tests/files/a0/b0/b00.yaml']
很多fnmatch
模式匹配整个文件名本身,而不仅仅是文件名。
configfiles = glob.glob('C:/Users/sam/Desktop/**/*.txt")
不适用于所有情况,而是使用glob2
configfiles = glob2.glob('C:/Users/sam/Desktop/**/*.txt")
如果你可以安装glob2包…
import glob2 filenames = glob2.glob("C:\\top_directory\\**\\*.ext") # Where ext is a specific file extension folders = glob2.glob("C:\\top_directory\\**\\")
所有文件名和文件夹:
all_ff = glob2.glob("C:\\top_directory\\**\\**")
正如Martijn所指出的,glob只能通过Python 3.5中引入的**
运算符来实现。 由于OP明确要求glob模块,下面将返回一个惰性评估迭代器,其行为相似
import os, glob, itertools configfiles = itertools.chain.from_iterable(glob.iglob(os.path.join(root,'*.txt')) for root, dirs, files in os.walk('C:/Users/sam/Desktop/file1/'))
请注意,尽pipe这种方法只能在configfiles
上迭代一次。 如果你需要一个可以在多个操作中使用的configfiles列表,你将不得不使用list(configfiles)
来明确地创build它。
如果你正在运行Python 3.4+,你可以使用pathlib
模块。 Path.glob()
方法支持**
模式,这意味着“这个目录和所有子目录,recursion”。 它返回一个生成器生成所有匹配文件的Path
对象。
from pathlib import Path configfiles = Path("C:/Users/sam/Desktop/file1/").glob("**/*.txt")