我了解os.walk吗?

时间:2012-06-12 00:01:53

标签: python file

os.walk(startdir)中root,dir,file的循环是通过这些步骤完成的吗?

for root in os.walk(startdir) 
    for dir in root 
        for files in dir
  1. 获取启动目录的根目录:C:\ dir1 \ dir2 \ startdir

  2. 在C:\ dir1 \ dir2 \ startdir中获取文件夹并返回文件夹列表“dirlist”

  3. 获取第一个dirlist项目中的文件,并返回文件列表“filelist”作为文件列表列表的第一项。

  4. 移动到dirlist中的第二项并返回此文件夹“filelist2”中的文件列表作为文件列表列表的第二项。等

  5. 移至foldertree中的下一个根并从2.等开始

  6. 右?或者它首先得到所有的根,然后所有的第二个和所有文件第三个?

6 个答案:

答案 0 :(得分:26)

os.walk返回一个生成器,它创建一个值元组(current_path,current_path中的目录,current_path中的文件)。

每次调用生成器时,它都会递归地跟随每个目录,直到调用walk的初始目录中没有其他子目录可用。

因此,

os.walk('C:\dir1\dir2\startdir').next()[0] # returns 'C:\dir1\dir2\startdir'
os.walk('C:\dir1\dir2\startdir').next()[1] # returns all the dirs in 'C:\dir1\dir2\startdir'
os.walk('C:\dir1\dir2\startdir').next()[2] # returns all the files in 'C:\dir1\dir2\startdir'

所以

import os.path
....
for path, directories, files in os.walk('C:\dir1\dir2\startdir'):
     if file in files:
          print 'found %s' % os.path.join(path, file)

或者

def search_file(directory = None, file = None):
    assert os.path.isdir(directory)
    for cur_path, directories, files in os.walk(directory):
        if file in files:
            return os.path.join(directory, cur_path, file)
    return None

或者如果你想查找文件,你可以这样做:

import os
def search_file(directory = None, file = None):
    assert os.path.isdir(directory)
    current_path, directories, files = os.walk(directory).next()
    if file in files:
        return os.path.join(directory, file)
    elif directories == '':
        return None
    else:
        for new_directory in directories:
            result = search_file(directory = os.path.join(directory, new_directory), file = file)
            if result:
                return result
        return None

答案 1 :(得分:5)

简单来说,os.walk()将生成路径,文件夹,给定路径中存在的文件的元组,并将继续遍历子文件夹。

import os.path
path=input(" enter the path\n")
for path,subdir,files in os.walk(path):
   for name in subdir:
       print os.path.join(path,name) # will print path of directories
   for name in files:    
       print os.path.join(path,name) # will print path of files

这将生成子目录中所有子目录,文件和文件的路径

答案 2 :(得分:3)

以下是os.walk()如何使用以及使用一些os函数进行解释的简短示例。

首先请注意,os.walk()会返回三个项目,根目录,当前根目录下方的目录列表(dirs)以及在这些项目中找到的文件列表目录。 documentation会为您提供更多信息。

dirs将包含根目录下方的目录列表,文件将包含这些目录中找到的所有文件的列表。在下一次迭代中,上一个dirs列表中的每个目录将依次承担root的角色,搜索将从那里继续,只有在当前级别之后才会进入某个级别搜索。

代码示例:这将搜索,计算和打印指定搜索目录(您的根目录)下的.jpg.gif文件的名称。它还使用os.path.splitext()函数将文件的基础与其扩展名分开,并使用os.path.join()函数为您提供全名,包括找到的图像文件的路径。

import os

searchdir = r'C:\your_root_dir'  # your search starts in this directory (your root) 

count = 0
for root, dirs, files in os.walk(searchdir):
    for name in files:
        (base, ext) = os.path.splitext(name) # split base and extension
        if ext in ('.jpg', '.gif'):          # check the extension
            count += 1
            full_name = os.path.join(root, name) # create full path
            print(full_name)

print('\ntotal number of .jpg and .gif files found: %d' % count)

答案 3 :(得分:2)

os.walk的工作方式与上面的有点不同。基本上,它返回(路径,目录,文件)的元组。要查看此内容,请尝试以下操作:

import pprint
import os
pp=pprint.PrettyPrinter(indent=4)
for dir_tuple in os.walk("/root"):
    pp.pprint(dir_tuple)

...你会看到循环的每次迭代都会打印一个目录名,列出该目录中所有目录的名称,以及该目录中所有文件的另一个列表。然后,os.walk将进入子目录列表中的每个目录并执行相同的操作,直到遍历了原始根目录的所有子目录。了解递归以了解其工作原理可能会有所帮助。

答案 4 :(得分:2)

最小的可运行示例

这就是我喜欢学习的东西:

mkdir root
cd root
mkdir \
  d0 \
  d1 \
  d0/d0_d1
touch \
   f0 \
   d0/d0_f0 \
   d0/d0_f1 \
   d0/d0_d1/d0_d1_f0
tree

输出:

.
├── d0
│   ├── d0_d1
│   │   └── d0_d1_f0
│   ├── d0_f0
│   └── d0_f1
├── d1
└── f0

main.py

#!/usr/bin/env python3
import os
for path, dirnames, filenames in os.walk('root'):
    print('{} {} {}'.format(repr(path), repr(dirnames), repr(filenames)))

输出:

'root' ['d0', 'd1'] ['f0']
'root/d0' ['d0_d1'] ['d0_f0', 'd0_f1']
'root/d0/d0_d1' [] ['d0_d1_f0']
'root/d1' [] []

这使所有事情变得清晰起来:

  • path是每个步骤的根目录
  • dirnames是每个path
  • 中目录名的列表
  • filenames是每个path
  • 中文件基名的列表

已在Ubuntu 16.04,Python 3.5.2上进行了测试。

修改dirnames会更改树的递归顺序

这基本上是您要记住的唯一其他事情。

例如,如果您在dirnames上进行以下操作,则会影响遍历:

步行文件或目录

如果要遍历的输入是文件或目录,则可以按以下方式处理它:

#!/usr/bin/env python3

import os
import sys

def walk_file_or_dir(root):
    if os.path.isfile(root):
        dirname, basename = os.path.split(root)
        yield dirname, [], [basename]
    else:
        for path, dirnames, filenames in os.walk(root):
            yield path, dirnames, filenames

for path, dirnames, filenames in walk_file_or_dir(sys.argv[1]):
    print(path, dirnames, filenames)

答案 5 :(得分:0)

我的回答非常基本和简单。我自己是一个初学者,通过搜索网络找到了我的答案(参见 esp. the good documentation at docs.python.org)并尝试一些测试代码,例如这个:

for root, dirs, files in os.walk(startdir)
    print ("__________________")
    print (root)
    for file in files:
        print ("---",file)

这会打印出目录树,其中每个目录(起始目录和包含的子目录)前面有一行,后面是其中包含的文件。

我认为你必须记住两件事:

(1) os.walk 生成一个三元组(三元组) where

  • root 是一个包含根目录名称的字符串

  • dirs 是字符串的列表:直接包含在根目录中的目录名称,即在第一级,没有可能包含在目录中的子目录 他们;

  • filenames 是字符串的列表:直接包含在根目录中的文件名。

(2) for 循环如

for root, subdirs, files in os.walk(YourStartDir)

遍历根目录及其所有子目录。每个文件都不需要一步;它只是扫描目录树,并在每一步(对于树中的每个目录)填充其中包含的文件名列表和直接包含在其中的子目录列表。如果您有 n 个目录(包括根目录及其子目录),for 循环将循环 n 次,即 它需要 n 步。 您可以编写一小段测试代码来检查这一点,例如使用计数器。 在每一步,它都会生成一个 3 元组:一个字符串加上两个(可能是空的)字符串列表。 在这个例子中,三元组的元素被称为:“root”、“subdirs”、“files”,但这些名称由你决定;如果您的代码是

for a, b, c in os.walk(startdir)

三元组的元素将被称为“a”、“b”、“c”。

让我们回到测试代码:

for root, dirs, files in os.walk(startdir)
    print ("__________________")
    print (root)
    for file in files:
        print ("---",file)

第一个循环:root 是您在输入中给出的目录(起始路径,起始目录:一个字符串),dirs 是包含的子目录名称的列表(但不是名称的列表)其中包含的目录), files 是包含文件的列表。在测试代​​码中,我们没有使用列表“dirs”。

第二次循环:root 现在是第一个子目录,dirs 是包含在其中的子目录的列表,files 是包含在其中的文件的列表。< /p>

... 依此类推,直到到达树中的最后一个子目录。

os.walk 有三个可选参数:您可以在网上找到很多关于它们及其用途的信息,但我认为您的问题是关于 os.walk 的基础知识。