【问题标题】:Using os.walk() to recursively traverse directories in PythonPython中使用os.walk()递归遍历目录
【发布时间】:2013-06-01 23:23:22
【问题描述】:

我想从根目录导航到其中的所有其他目录并打印相同的内容。

这是我的代码:

#!/usr/bin/python

import os
import fnmatch

for root, dir, files in os.walk("."):
        print root
        print ""
        for items in fnmatch.filter(files, "*"):
                print "..." + items
        print ""

这是我的 O/P:

.

...Python_Notes
...pypy.py
...pypy.py.save
...classdemo.py
....goutputstream-J9ZUXW
...latest.py
...pack.py
...classdemo.pyc
...Python_Notes~
...module-demo.py
...filetype.py

./packagedemo

...classdemo.py
...__init__.pyc
...__init__.py
...classdemo.pyc

以上,../packagedemo 是目录。

但是,我需要按以下方式打印 O/P:

A
---a.txt
---b.txt
---B
------c.out

以上,AB 是目录,其余的是文件。

【问题讨论】:

  • 我想在这里添加这个小帖子,关于python的力量:>>> print 2 * '--' ----

标签: python os.walk


【解决方案1】:

您还可以使用pathlib.Path()递归遍历文件夹并列出其所有内容

from pathlib import Path


def check_out_path(target_path, level=0):
    """"
    This function recursively prints all contents of a pathlib.Path object
    """
    def print_indented(folder, level):
        print('\t' * level + folder)

    print_indented(target_path.name, level)
    for file in target_path.iterdir():
        if file.is_dir():
            check_out_path(file, level+1)
        else:
            print_indented(file.name, level+1)


my_path = Path(r'C:\example folder')
check_out_path(my_path)

输出:

example folder
    folder
        textfile3.txt
    textfile1.txt
    textfile2.txt

【讨论】:

  • 我喜欢这个,因为它使用了pathlib。谢谢
【解决方案2】:

最好的办法

def traverse_dir_recur(dir):
    import os
    l = os.listdir(dir)
    for d in l:
        if os.path.isdir(dir + d):
            traverse_dir_recur(dir+  d +"/")
        else:
            print(dir + d)

【讨论】:

  • 在 Python3 中不适合我。我假设错误在dir + d 中,这可能会在没有目录分隔符的情况下连接它们。使用os.path.join 连接目录和文件名可能会更好
【解决方案3】:

试试这个:

import os
root_name = next(os.walk("."))[0]
dir_names = next(os.walk("."))[1]
file_names = next(os.walk("."))[2]

在这里,我假设您的路径为“。”其中 root_file 和其他目录在那里。 所以,基本上我们只是通过使用 next() 调用来迭代整个树,因为我们的 os.walk 只是生成函数。 通过这样做,我们可以将所有目录和文件名分别保存在 dir_names 和 file_names 中。

【讨论】:

    【解决方案4】:

    递归遍历一个目录,您可以从当前目录中的所有目录中获取所有文件,并从当前目录中获取所有目录 - 因为上面的代码不简单(恕我直言):

    for root, dirs, files in os.walk(rootFolderPath):
        for filename in files:
            doSomethingWithFile(os.path.join(root, filename))
        for dirname in dirs:
            doSomewthingWithDir(os.path.join(root, dirname))
    

    【讨论】:

    • 最有帮助的答案。请注意,os.path.join(root, filename) 给出了文件的完整路径,即使文件嵌套在多个目录中。
    【解决方案5】:

    这是为文件夹名称做的:

    def printFolderName(init_indent, rootFolder):
        fname = rootFolder.split(os.sep)[-1]
        root_levels = rootFolder.count(os.sep)
        # os.walk treats dirs breadth-first, but files depth-first (go figure)
        for root, dirs, files in os.walk(rootFolder):
            # print the directories below the root
            levels = root.count(os.sep) - root_levels
            indent = ' '*(levels*2)
            print init_indent + indent + root.split(os.sep)[-1]
    

    【讨论】:

      【解决方案6】:

      这会给你想要的结果

      #!/usr/bin/python
      
      import os
      
      # traverse root directory, and list directories as dirs and files as files
      for root, dirs, files in os.walk("."):
          path = root.split(os.sep)
          print((len(path) - 1) * '---', os.path.basename(root))
          for file in files:
              print(len(path) * '---', file)
      

      【讨论】:

      • path = os.path.relpath(root, basepath).split(os.sep)
      • @Ajay 偏执,总是使用os.walk(u"."),因为路径可以是 Unicode。
      • 更好,os.path.curdir
      • 我使用os.path.walk 有一段时间了,所以os.walk 对我来说是新的!凉豆。
      • @Semprini 在你的代码中basepath 等于什么?
      【解决方案7】:

      给定一个文件夹名称,递归遍历其整个层次结构。

      #! /usr/local/bin/python3
      # findLargeFiles.py - given a folder name, walk through its entire hierarchy
      #                   - print folders and files within each folder
      
      import os
      
      def recursive_walk(folder):
          for folderName, subfolders, filenames in os.walk(folder):
              if subfolders:
                  for subfolder in subfolders:
                      recursive_walk(subfolder)
              print('\nFolder: ' + folderName + '\n')
              for filename in filenames:
                  print(filename + '\n')
      
      recursive_walk('/name/of/folder')
      

      【讨论】:

      • 不需要递归调用 os.walk,因为它已经使递归变平了。这就是它返回 folderName 参数的原因。
      【解决方案8】:

      试试这个;简单的一个

       #!/usr/bin/python
       import os
       # Creating an empty list that will contain the already traversed paths
       donePaths = []
       def direct(path):
             for paths,dirs,files in os.walk(path):
                   if paths not in donePaths:
                          count = paths.count('/')
                          if files:
                                for ele1 in files:
                                      print '---------' * (count), ele1
                          if dirs:
                                for ele2 in dirs:
                                      print '---------' * (count), ele2
                                      absPath = os.path.join(paths,ele2)
                    # recursively calling the direct function on each directory
                                      direct(absPath)
                         # adding the paths to the list that got traversed 
                                      donePaths.append(absPath)
      
       path = raw_input("Enter any path to get the following Dir Tree ...\n")
       direct(path)
      

      ========下面的输出========

       /home/test
       ------------------ b.txt
       ------------------ a.txt
       ------------------ a
       --------------------------- a1.txt
       ------------------ b
       --------------------------- b1.txt
       --------------------------- b2.txt
       --------------------------- cde
       ------------------------------------ cde.txt
       ------------------------------------ cdeDir
       --------------------------------------------- cdeDir.txt
       ------------------ c
       --------------------------- c.txt
       --------------------------- c1
       ------------------------------------ c1.txt
       ------------------------------------ c2.txt
      

      【讨论】:

      • 检查已经遍历的路径有什么意义?如果是检测链接引起的循环,os.walk 显然默认不跟随链接。还有其他情况吗?
      【解决方案9】:

      试试这个:

      #!/usr/bin/env python
      # -*- coding: utf-8 -*-
      
      """FileTreeMaker.py: ..."""
      
      __author__  = "legendmohe"
      
      import os
      import argparse
      import time
      
      class FileTreeMaker(object):
      
          def _recurse(self, parent_path, file_list, prefix, output_buf, level):
              if len(file_list) == 0 \
                  or (self.max_level != -1 and self.max_level <= level):
                  return
              else:
                  file_list.sort(key=lambda f: os.path.isfile(os.path.join(parent_path, f)))
                  for idx, sub_path in enumerate(file_list):
                      if any(exclude_name in sub_path for exclude_name in self.exn):
                          continue
      
                      full_path = os.path.join(parent_path, sub_path)
                      idc = "┣━"
                      if idx == len(file_list) - 1:
                          idc = "┗━"
      
                      if os.path.isdir(full_path) and sub_path not in self.exf:
                          output_buf.append("%s%s[%s]" % (prefix, idc, sub_path))
                          if len(file_list) > 1 and idx != len(file_list) - 1:
                              tmp_prefix = prefix + "┃  "
                          else:
                              tmp_prefix = prefix + "    "
                          self._recurse(full_path, os.listdir(full_path), tmp_prefix, output_buf, level + 1)
                      elif os.path.isfile(full_path):
                          output_buf.append("%s%s%s" % (prefix, idc, sub_path))
      
          def make(self, args):
              self.root = args.root
              self.exf = args.exclude_folder
              self.exn = args.exclude_name
              self.max_level = args.max_level
      
              print("root:%s" % self.root)
      
              buf = []
              path_parts = self.root.rsplit(os.path.sep, 1)
              buf.append("[%s]" % (path_parts[-1],))
              self._recurse(self.root, os.listdir(self.root), "", buf, 0)
      
              output_str = "\n".join(buf)
              if len(args.output) != 0:
                  with open(args.output, 'w') as of:
                      of.write(output_str)
              return output_str
      
      if __name__ == "__main__":
          parser = argparse.ArgumentParser()
          parser.add_argument("-r", "--root", help="root of file tree", default=".")
          parser.add_argument("-o", "--output", help="output file name", default="")
          parser.add_argument("-xf", "--exclude_folder", nargs='*', help="exclude folder", default=[])
          parser.add_argument("-xn", "--exclude_name", nargs='*', help="exclude name", default=[])
          parser.add_argument("-m", "--max_level", help="max level",
                              type=int, default=-1)
          args = parser.parse_args()
          print(FileTreeMaker().make(args))
      

      你会得到这个:

      root:.
      [.]
      ┣━[.idea]
      ┃  ┣━[scopes]
      ┃  ┃  ┗━scope_settings.xml
      ┃  ┣━.name
      ┃  ┣━Demo.iml
      ┃  ┣━encodings.xml
      ┃  ┣━misc.xml
      ┃  ┣━modules.xml
      ┃  ┣━vcs.xml
      ┃  ┗━workspace.xml
      ┣━[test1]
      ┃  ┗━test1.txt
      ┣━[test2]
      ┃  ┣━[test2-2]
      ┃  ┃  ┗━[test2-3]
      ┃  ┃      ┣━test2
      ┃  ┃      ┗━test2-3-1
      ┃  ┗━test2
      ┣━folder_tree_maker.py
      ┗━tree.py
      

      【讨论】:

      • 你好,我真的很喜欢你的脚本,但是对于我正在处理的项目来说它有点太复杂了,有没有机会我可以将它作为一个小函数,只有 -r 参数在场吗?
      • 如何打印成.txt?我试过print(FileTreeMaker().make(args),file=tree),但它给了我'charmap' codec can't encode characters in position 17-21: character maps to &lt;undefined&gt;
      • idc 代表什么
      • 我也用os.listdir() 写过类似的东西。你的好多了;我无法正确地递归,它只能工作 2 或 3 层深。最后,我决定改用os.walk() 从头开始​​再试一次,我认为这会更合适。我很惊讶你在这里根本没有使用它。
      【解决方案10】:
      import os
      
      os.chdir('/your/working/path/')
      dir = os.getcwd()
      list = sorted(os.listdir(dir))
      marks = ""
      
      for s_list in list:
          print marks + s_list
          marks += "---"
          tree_list = sorted(os.listdir(dir + "/" + s_list))
          for i in tree_list:
              print marks + i
      

      【讨论】:

      • 这看起来不像遍历整棵树。
      【解决方案11】:
      #!/usr/bin/python
      
      import os 
      
      def tracing(a):
          global i>
          for item in os.listdir(a):
              if os.path.isfile(item):
                  print i + item 
              else:
                  print i + item 
                  i+=i
                  tracing(item)
      
      i = "---"
      tracing(".")
      

      【讨论】:

        【解决方案12】:

        您可以使用os.walk,这可能是最简单的解决方案,但这里还有一个值得探索的想法:

        import sys, os
        
        FILES = False
        
        def main():
            if len(sys.argv) > 2 and sys.argv[2].upper() == '/F':
                global FILES; FILES = True
            try:
                tree(sys.argv[1])
            except:
                print('Usage: {} <directory>'.format(os.path.basename(sys.argv[0])))
        
        def tree(path):
            path = os.path.abspath(path)
            dirs, files = listdir(path)[:2]
            print(path)
            walk(path, dirs, files)
            if not dirs:
                print('No subfolders exist')
        
        def walk(root, dirs, files, prefix=''):
            if FILES and files:
                file_prefix = prefix + ('|' if dirs else ' ') + '   '
                for name in files:
                    print(file_prefix + name)
                print(file_prefix)
            dir_prefix, walk_prefix = prefix + '+---', prefix + '|   '
            for pos, neg, name in enumerate2(dirs):
                if neg == -1:
                    dir_prefix, walk_prefix = prefix + '\\---', prefix + '    '
                print(dir_prefix + name)
                path = os.path.join(root, name)
                try:
                    dirs, files = listdir(path)[:2]
                except:
                    pass
                else:
                    walk(path, dirs, files, walk_prefix)
        
        def listdir(path):
            dirs, files, links = [], [], []
            for name in os.listdir(path):
                path_name = os.path.join(path, name)
                if os.path.isdir(path_name):
                    dirs.append(name)
                elif os.path.isfile(path_name):
                    files.append(name)
                elif os.path.islink(path_name):
                    links.append(name)
            return dirs, files, links
        
        def enumerate2(sequence):
            length = len(sequence)
            for count, value in enumerate(sequence):
                yield count, count - length, value
        
        if __name__ == '__main__':
            main()
        

        您可能会从 Windows 终端中的 TREE 命令中识别出以下文档:

        Graphically displays the folder structure of a drive or path.
        
        TREE [drive:][path] [/F] [/A]
        
           /F   Display the names of the files in each folder.
           /A   Use ASCII instead of extended characters.
        

        【讨论】:

          【解决方案13】:

          os 包中有更合适的函数。但是如果你必须使用os.walk,这就是我想出的

          def walkdir(dirname):
              for cur, _dirs, files in os.walk(dirname):
                  pref = ''
                  head, tail = os.path.split(cur)
                  while head:
                      pref += '---'
                      head, _tail = os.path.split(head)
                  print(pref+tail)
                  for f in files:
                      print(pref+'---'+f)
          

          输出:

          >>> walkdir('.')
          .
          ---file3
          ---file2
          ---my.py
          ---file1
          ---A
          ------file2
          ------file1
          ---B
          ------file3
          ------file2
          ------file4
          ------file1
          ---__pycache__
          ------my.cpython-33.pyc
          

          【讨论】:

          • 那么还有哪些比较适合的功能呢? (如果重要的话,在 3.5 中)
          • 抱歉,没机会记住我的意思。我的意思可能是os.listdir,但@ajay 的解决方案胜过这一点。
          猜你喜欢
          • 2023-01-09
          • 2017-05-31
          • 2013-01-23
          • 2019-06-24
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2012-04-07
          • 2018-11-15
          相关资源
          最近更新 更多