我想打开一个文件夹中的一系列子文件夹,找到一些文本文件并打印出文本文件的某些行。我正在使用以下代码:
configfiles = glob.glob('C:/Users/sam/Desktop/file1/*.txt')
但这个命令无法访问子文件夹。有人知道如何使用相同的命令来访问子文件夹吗?
我想打开一个文件夹中的一系列子文件夹,找到一些文本文件并打印出文本文件的某些行。我正在使用以下代码:
configfiles = glob.glob('C:/Users/sam/Desktop/file1/*.txt')
但这个命令无法访问子文件夹。有人知道如何使用相同的命令来访问子文件夹吗?
**/
功能:configfiles = glob.glob('C:/Users/sam/Desktop/file1/**/*.txt', recursive=True)
recursive
时,路径分隔符后跟**
将匹配0个或多个子目录。glob.glob()
不能递归地列出子目录中的文件。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')]
这将递归地遍历您的目录,并返回匹配.txt
文件的所有绝对路径。在这种特定情况下,fnmatch.filter()
可能过于复杂,您也可以使用.endswith()
测试:
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')]
目录路径
中的文本文件。 - Martijn Pieters**/
功能时将recursive=False
设置为false无法提供给定文件夹中的文件列表,而是其子文件夹中的文件? - Dr_Zaszuś*/*
。 - Martijn Pieters这个主题存在很多困惑。让我来澄清一下(Python 3.7):
glob.glob('*.txt') :
匹配当前目录中所有以“.txt”结尾的文件glob.glob('*/*.txt') :
同上glob.glob('**/*.txt') :
只匹配直接子目录中以“.txt”结尾的文件,不包括当前目录glob.glob('*.txt',recursive=True) :
同第1条glob.glob('*/*.txt',recursive=True) :
同第3条glob.glob('**/*.txt',recursive=True):
匹配当前目录和所有子目录中以“.txt”结尾的文件因此,最好总是指定 recursive=True
。
查找直接子目录中的文件:
configfiles = glob.glob(r'C:\Users\sam\Desktop\*\*.txt')
如果需要递归遍历所有子目录的递归版本,你可以使用 **
并传递参数 recursive=True
自 Python 3.5 开始 :
configfiles = glob.glob(r'C:\Users\sam\Desktop\**\*.txt', recursive=True)
两个函数调用都返回列表。您可以使用glob.iglob()
逐个返回路径。或者使用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
这两种方法都会返回迭代器(你可以逐个获取路径)。
glob()
会支持目录中的模式匹配。 - Martijn Pieters**
递归情况的文档更新。但是为了使**
正常工作,你必须设置recursion=True
开关。 - Martijn Pietersglob2包支持通配符并具有相当快的速度
code = '''
import glob2
glob2.glob("files/*/**")
'''
timeit.timeit(code, number=1)
在我的笔记本电脑上,匹配超过60,000个文件路径大约需要2秒钟。
import formic
fileset = formic.FileSet(include="**/*.txt", directory="C:/Users/sam/Desktop/")
声明 - 我是这个软件包的作者。
glob2
的情况下实现类似于glob.glob
的功能。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
模式匹配整个文件名本身,而不仅仅是文件名。对于当然已经在其他答案中提到的第一种选项,这里的目标是展示glob在内部使用了os.scandir
,并直接给出这个答案。
如前所述,使用Python 3.5+很容易:
import glob
for f in glob.glob('d:/temp/**/*', recursive=True):
print(f)
#d:\temp\New folder
#d:\temp\New Text Document - Copy.txt
#d:\temp\New folder\New Text Document - Copy.txt
#d:\temp\New folder\New Text Document.txt
from pathlib import Path
for f in Path('d:/temp').glob('**/*'):
print(f)
os.scandir
是 glob
内部所使用的操作。因此以下是如何直接使用 yield
来实现:
def listpath(path):
for f in os.scandir(path):
f2 = os.path.join(path, f)
if os.path.isdir(f):
yield f2
yield from listpath(f2)
else:
yield f2
for f in listpath('d:\\temp'):
print(f)
configfiles = glob2.glob('C:/Users/sam/Desktop/**/*.txt')
这种情况下并不适用,建议使用glob2。
configfiles = glob2.glob('C:/Users/sam/Desktop/**/*.txt")
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\\**\\**")
pathlib
模块。 Path.glob()
方法支持使用 **
模式,意思是“这个目录以及所有子目录,递归地”。它返回一个生成器,为所有匹配的文件产生 Path
对象。from pathlib import Path
configfiles = Path("C:/Users/sam/Desktop/file1/").glob("**/*.txt")