Python的几种不同的文件遍历方式、对比和优缺点


本次列举python的几种不同的文件遍历方式。

运行环境

原始文件目录结构

E:
|-files
	|-.git
		|-config
		|-HEAD
		|-index
		|-hooks
			|-applypatch-msg.sample
			|-commit-msg.sample
	|.vscode
		|-launch.json
		|-tasks.json
	|-src
		|-helloworld.h
		|-helloworld.cpp
	|-main.cpp

glob 库

注意: 本方式无法遍历指令目录下以点号"."开头的文件夹,比如".git" ".vs"

glob模块是最简单的模块之一,内容非常少。用它可以查找符合特定规则的文件路径名。跟使用windows下的文件搜索差不多。查找文件只用到三个匹配符:"*", "?", "[]"

"*"匹配0个或多个字符;
"?"匹配单个字符;
"[]"匹配指定范围内的字符,如:[0-9]匹配数字。

glob.glob 方式

函数定义: def glob(pathname, *, recursive=False):

函数功能: 匹配所有的符合条件的文件,并将其以list的形式返回

参数说明: 它只有一个参数pathname,定义了文件路径匹配规则,这里可以是绝对路径,也可以是相对路径。

下面是使用glob.glob的例子:

遍历指定目录下的所有文件,不包括子文件

import os
import glob

def func1():
    for strFile in glob.glob(r'E:\files\*', recursive=True):
        print('%s : "%s"' % (("file" if os.path.isfile(strFile) else "dir "), strFile))


if __name__ == '__main__':
    func1()

# 输出为:
# file : "E:\files\main.cpp"
# dir  : "E:\files\src"

遍历指定目录下的所有文件,包括子文件

import os
import glob

def func1():
    for strFile in glob.glob(r'E:\files\**', recursive=True):
        print('%s : "%s"' % (("file" if os.path.isfile(strFile) else "dir "), strFile))


if __name__ == '__main__':
    func1()

# 输出为:
# dir  : "E:\files\"
# file : "E:\files\main.cpp"
# dir  : "E:\files\src"
# file : "E:\files\src\helloworld.cpp"
# file : "E:\files\src\helloworld.h"

获取指定目录下的所有cpp文件

import os
import glob

def func1():
    for strFile in glob.glob(r'E:\files\*\*.cpp', recursive=True):
        print('%s : "%s"' % (("file" if os.path.isfile(strFile) else "dir "), strFile))


if __name__ == '__main__':
    func1()

# 输出为:
# file :"E:\files\src\helloworld.cpp"

glob.iglob 方式

函数定义: def iglob(pathname, *, recursive=False):

函数功能: 获取一个可遍历对象,使用它可以逐个获取匹配的文件路径名。

与glob.glob()的区别是:glob.glob同时获取所有的匹配路径,而glob.iglob一次只获取一个匹配路径,相当于迭代器。查看glob.glob()方法的源码可获知两者的关系。

def glob(pathname, *, recursive=False):
    return list(iglob(pathname, recursive=recursive))

下面是一个简单的例子:

import glob
#父目录中的.py文件
f = glob.iglob(r'../*.py')
print (f) #<generator object iglob at 0x00B9FF80>
for py in f:
    print (py)

pathlib库

Path(‘dir’).rglob(“pattern”) 递归方式

函数定义: def rglob(self, pattern):

函数功能:

Recursively yield all existing files (of any kind, including directories) matching the given relative pattern, anywhere in this subtree.

递归遍历指定目录下的所有文件

import os
from pathlib import Path

def func2():
    path = Path(r'E:\files')
    for p in path.rglob("*"):
        print('%s : "%s"' % (("file" if os.path.isfile(str(p)) else "dir "), str(p)))


if __name__ == '__main__':
    func2()


# 输出为:
# dir  : "E:\files\.git"
# dir  : "E:\files\.vscode"
# file : "E:\files\main.cpp"
# dir  : "E:\files\src"
# file : "E:\files\.git\config"
# file : "E:\files\.git\HEAD"
# dir  : "E:\files\.git\hooks"
# file : "E:\files\.git\index"
# file : "E:\files\.git\hooks\applypatch-msg.sample"
# file : "E:\files\.git\hooks\commit-msg.sample"
# file : "E:\files\.vscode\launch.json"
# file : "E:\files\.vscode\tasks.json"
# file : "E:\files\src\helloworld.cpp"
# file : "E:\files\src\helloworld.h"

递归遍历指定目录下的所有cpp文件

import os
from pathlib import Path

def func2():
    path = Path(r'E:\files')
    for p in path.rglob("*.cpp"):
        print('%s : "%s"' % (("file" if os.path.isfile(str(p)) else "dir "), str(p)))


if __name__ == '__main__':
    func2()

# 输出
# file : "E:\files\main.cpp"
# file : "E:\files\src\helloworld.cpp"

Path(‘dir’).glob(“pattern”) 非递归方式

函数定义: def glob(self, pattern):

函数功能:

Iterate over this subtree and yield all existing files (of any kind, including directories) matching the given relative pattern.

非递归遍历指定目录下的所有文件

import os
from pathlib import Path

def func2():
    path = Path(r'E:\files')
    for p in path.glob("*"):
        print('%s : "%s"' % (("file" if os.path.isfile(str(p)) else "dir "), str(p)))


if __name__ == '__main__':
    func2()

# 输出
# dir  : "E:\files\.git"
# dir  : "E:\files\.vscode"
# file : "E:\files\main.cpp"
# dir  : "E:\files\src"

非递归遍历指定目录下的所有cpp文件

import os
from pathlib import Path

def func2():
    path = Path(r'E:\files')
    for p in path.glob("*.cpp"):
        print('%s : "%s"' % (("file" if os.path.isfile(str(p)) else "dir "), str(p)))


if __name__ == '__main__':
    func2()

# 输出
# file : "E:\files\main.cpp"

os.walk方式

函数定义: def walk(top, topdown=True, onerror=None, followlinks=False):

函数功能: 遍历目录,topdown=false表示先返回目录,后返回文件

参数说明:

top:表示需要遍历的目录树的路径。
topdown: topdown的默认值是True,表示首先返回根目录树下的文件,然后遍历目录树下的子目录。值设为False时,则表示先遍历目录树下的子目录,返回子目录下的文件,最后返回根目录下的文件。
onerror: onerror的默认值是None,表示忽略文件遍历时产生的错误。如果不为空,则提供一个自定义函数提示错误信息后继续遍历或抛出异常中止遍历。
该函数返回一个列表,列表中的每一个元素都是一个元组,该元组有3个元素,分别表示每次遍历的路径名,目录列表和文件列表。
followlinks: 默认情况下,os.walk 不会遍历软链接指向的子目录,若有需要请将followlinks设定为true

该函数返回一个列表,列表中的每一个元素都是一个元组,该元组有3个元素,分别表示每次遍历的路径名,目录列表和文件列表。

>>> r=os.walk('d:\\test2',topdown=False)
>>> r
<generator object walk at 0x0000000004C5D480>
>>> list(r)
[('d:\\test2\\dir1', [], []), ('d:\\test2\\dir2\\dir3', [], ['2.txt', '33.bmp']), ('d:\\test2\\dir2', ['dir3'], ['1.txt']), ('d:\\test2', ['dir1', 'dir2'], [])]
用root,dirs,files三个变量遍历目录的的目录层级,目录层级的子目录,目录层级下的文件
 for root,dirs,files in os.walk(r'd:\\test2',topdown=False):
root:表示当前遍历到哪一级目录了,目录的名字是谁
dirs:表示root下有哪些子目录
files:表示root下边有几个文件

遍历某一文件下的所有文件,首先返回根目录树下的文件,然后遍历目录树下的子目录

import os

def func3():
    for root, dirs, files in os.walk(r'E:\files', topdown=True):
        for name in files:
            print('file : ' + os.path.join(root, name))
        for name in dirs:
            print('dir  : ' + os.path.join(root, name))


if __name__ == '__main__':
    func3()

# 输出
# file : E:\files\main.cpp
# dir  : E:\files\.git
# dir  : E:\files\.vscode
# dir  : E:\files\src
# file : E:\files\.git\config
# file : E:\files\.git\HEAD
# file : E:\files\.git\index
# dir  : E:\files\.git\hooks
# file : E:\files\.git\hooks\applypatch-msg.sample
# file : E:\files\.git\hooks\commit-msg.sample
# file : E:\files\.vscode\launch.json
# file : E:\files\.vscode\tasks.json
# file : E:\files\src\helloworld.cpp
# file : E:\files\src\helloworld.h

遍历某一文件下的所有文件,先遍历目录树下的子目录,返回子目录下的文件

import os

def func3():
    for root, dirs, files in os.walk(r'E:\files', topdown=False):
        for name in files:
            print('file:' + os.path.join(root, name))
        for name in dirs:
            print('dir:' + os.path.join(root, name))


if __name__ == '__main__':
    func3()

# 输出
# file : E:\files\.git\hooks\applypatch-msg.sample
# file : E:\files\.git\hooks\commit-msg.sample
# file : E:\files\.git\config
# file : E:\files\.git\HEAD
# file : E:\files\.git\index
# dir  : E:\files\.git\hooks
# file : E:\files\.vscode\launch.json
# file : E:\files\.vscode\tasks.json
# file : E:\files\src\helloworld.cpp
# file : E:\files\src\helloworld.h
# file : E:\files\main.cpp
# dir  : E:\files\.git
# dir  : E:\files\.vscode
# dir  : E:\files\src

从以上例子可以看出,topdown设值不同,os.walk()返回的列表元素顺序不同(但不是相反),所以遍历后的结果也不同。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值