我们使用os,listdir()函数来列出目录下的所有文件和目录放入一个列表进行返回,但是listdir()函数不可对目录的子目录进行扫描。
print(os.listdir('/'))
输出:
['boot', 'dev', 'home', 'proc', 'run', 'sys', 'etc', 'root', 'var', 'tmp', 'usr', 'bin', 'sbin', 'lib', 'lib64', 'media', 'mnt', 'opt', 'srv', 'iso', 'redhat7.4-mount', '.autorelabel', 'directory', 'python']
很多时候我们需要将某个文件夹下的所有文件都要找出来,那么此时我们就需要os.walk()函数。os.walk()方法用于通过在目录了数中向下或向上游走,输出目录的文件名,该方法回访回一个生成器。
os.walk(top[, topdown=True[, οnerrοr=None[, followlinks=False]]])
top -- 是你所要遍历的目录的地址.
topdown -- 可选,为 True,则优先遍历top目录,
否则优先遍历 top 的子目录(默认为开启)。
onerror -- 可选,需要一个 callable 对象,当 walk 需要异常时,会调用。
followlinks -- 可选,如果为 True,则会遍历目录下的快捷方式,默认开启
return None
该函数没有返回值会使用yield关键字抛出一个存放当前
该层目录(root,dirs,files)的三元组,最终将所有目录层的的结果变为一个生成器
root 所指的是当前正在遍历的这个文件夹的本身的地址
dirs 是一个 list ,内容是该文件夹中所有的目录的名字(不包括子目录)
files 同样是 list , 内容是该文件夹中所有的文件(不包括子目录)
为了方便我们理解os.walk()最终抛出的数据的类型我们对它的生成器进行强制转换为list(),这样我们就可以看出其内部数据结构。
在我们的/mnt下有下面几个文件和目录
print(list(os.walk('/mnt',topdown = False)))
输出:
[('/mnt', ['dira', 'dirb'], ['file1', 'file2']), ('/mnt/dira', [], ['file_test_A']), ('/mnt/dirb', [], ['file_test_B'])]
这个列表(因为我们将生成器强制转化为列表)中的每一个元素都是一个元组,每一个元组都是都是一层目录,元组中的元素又代表了当前目录层的路径(根据赋给形参top的值来决定是绝对路径还是相对路径)、当前目录下有的文件目录、和当前目录下的文件。
当我们对生成器使用for循环时,会将每层一目录信息返回。
for info in os.walk('/mnt', topdown=True):
print(info)
print('***分隔符***')
输出:
('/mnt', ['dira', 'dirb'], ['file1', 'file2'])
***分隔符***
('/mnt/dira', [], ['file_test_A'])
***分隔符***
('/mnt/dirb', [], ['file_test_B'])
***分隔符***
注意:
这里抛出的值文件、路径和文件夹是分离的而不是在一起的 使用文件的据对路径一定要root+os.path.sep+filenames
下面两段代码就是我入过的坑
错误:
import os
def SearchAbsPath(dirname):
dirname = os.path.abspath(dirname)
filenames = list()
for root,dirs,files in os.walk(dirname, topdown=False): #扫描一层目录
for name in files:
filenames.append(dirname+os.path.sep+name) #每一个文件的绝对路径放入列表
print(dirname+os.path.sep+name)
return filenames
SearchAbsPath('/mnt')
输出:
/mnt/file_test_A
/mnt/file_test_B
/mnt/__init__.py
/mnt/file1
/mnt/file2
正确:
import os
def SearchAbsPath(dirname):
dirname = os.path.abspath(dirname)
filenames = list()
for root,dirs,files in os.walk(dirname, topdown=False): #扫描一层目录
for name in files:
filenames.append(root+os.path.sep+name) #每一个文件的绝对路径放入列表
print(root+os.path.sep+name)
return filenames
SearchAbsPath('.')
输出:
/mnt/dira/file_test_A
/mnt/dirb/file_test_B
/mnt/packeage/__init__.py
/mnt/file1
/mnt/file2
错误的代码,文件绝对路径=形参top的绝对路径+os.path.sep+文件名, 因此当我们们的top目录下还有多层目录时,我们水价格中间目录缺少,导致文件据对路径错误。
正确的代码,文件绝对路径 =root(在os.walk()传入的参数时绝对路径,root也就是绝对路径)+os.path.sep+文件名,不会缺失中间目录