回到一
目录遍历是一个经典话题,花些功夫也很值得。(好在之前了解过)实现目录遍历的方式有三种,递归、栈、队列。
递归一般是函数自己调用自己,一直到满足退出的条件。栈和队列就是数据结构,栈stack是后进先出,队列queue是先进先出。很好理解。(在python里没有这两种数据对象,实现上就是个list,看你怎么捣鼓。一般目录遍历使用递归就可以,简单快捷。感觉堆栈、队列更适合查找数据。)
递归的实现就很简单了,os库提供了三个方法,os.walk()、os.listdir()、os.scandir()
递归
walkdir实现
os.walk(top, topdown=True, onerror=None, followlinks=False)
,可以生成目录树(文件夹和子文件夹)中的文件夹名和文件名,通过设置topdown可以设置子目录的获取方式。
walkdir不太容易实现我们的需求,查看walkdir的源码会发现,是用scandir实现的子目录获取,但外层确是广度变脸,而docx需要逐行书写。
所以wlak比较适合获取目录下文件数量,或者文件和文件夹单独需求的场景。
import os
path = r'C:UserszhaobwDesktop测试'
for root, dirs, files in os.walk(path, topdown=False):
for name in files:
print(os.path.join(root, name))
for name in dirs:
print(os.path.join(root, name))
listdir实现
os.listdir(path)
listdir返回路径下的文件和文件夹,但是不获取子目录。直接返回一个list,简单粗暴。不适用目录结构多的场景。
import os
import os.path
def showdir(path, depth):
for item in os.listdir(path):
#print(item)
# if '.git' not in item:
print("| " * depth + "|--" + item)
newitem = path +os.sep+ item
#递归出口
if os.path.isdir(newitem):
showdir(newitem, depth+1)
if __name__ == '__main__':
path = r'C:UsersAdministratorDesktop测试'
showdir(path, 0)
scandir实现
os.scandir(path)
,scandir同listdir一样返回路径下的文件夹名和文件名,不处理子目录。返回一个迭代器对象。
import os
import os.path
def showdir(path, depth):
for item in os.scandir(path):
print("| " * depth + "+--" + item.name)
# #递归出口
if item.is_dir():
showdir(item.path, depth + 1)
if __name__ == '__main__':
path = r'C:UsersAdministratorDesktop测试'
showdir(path, 0)
栈
栈遍历目录又叫深度遍历,顺着一个路径一直往下找。上述实现scandir的代码就是深度遍历。
import os
path = r'C:UserszhaobwDesktop测试'
def getAllDirAndFile(path):
stack = [] # 空元素
stack.append(path)
# 循环遍历处理栈的内容,当栈里面的内容为空时退出
while len(stack) != 0:
# 从栈里取出元素
dirPath = stack.pop()
# 遍历dirPath目录下的所有文件
fileList = os.listdir(dirPath)
for fileName in fileList:
fileAbs = os.path.join(dirPath, fileName)
if os.path.isdir(fileAbs):
# 当当前目录时文件夹,进行入栈操作
print('文件夹' + fileName)
stack.append(fileAbs)
else:
print('普通文件' + fileName)
队列
栈遍历目录又叫深度遍历,同时从多个目录开始找,上述实现walkdir的代码就是深度遍历,查看打印的日志,一看便知。
import os
path = r'C:UserszhaobwDesktop测试'
def getAllDirAndFile(path):
# 创建队列
queue = collections.deque()
# 添加元素
queue.append(path) #[a]
while len(queue) != 0:
# 移除队列中的元素
dirPath = queue.popleft()
# 获取dirPath下的所有文件及文件夹
fileList = os.listdir(dirPath)
for fileName in fileList:
# 绝对路径
fileAbs = os.path.join(dirPath, fileName)
# 如果是文件夹就放到队列中
if os.path.isdir(fileAbs):
print('文件夹' + fileName)
queue.append(fileAbs)
else:
print('文件' + fileName)