【问题标题】:Directory-tree listing in PythonPython中的目录树列表
【发布时间】:2010-09-12 08:22:33
【问题描述】:

如何在 Python 中获取给定目录中所有文件(和目录)的列表?

【问题讨论】:

标签: python file directory subdirectory directory-tree


【解决方案1】:

你可以使用

os.listdir(path)

参考和更多的操作系统功能看这里:

【讨论】:

  • 原来的问题很模糊,不知道他们是否想要一个递归解决方案。 “目录中的所有文件”可以解释为递归。
  • @Tommy,“目录”是一个明确定义的数据结构,它指的是“ls”而不是“ls -R”。此外,几乎所有 UNIX 工具默认情况下都不会递归工作。我不知道提问者是什么意思,但他写的很清楚。
  • python 3 文档告诉您改用os.scandir,因为在许多情况下,它允许您阻止系统调用,从而提供免费加速(IPC 和 IO 都很慢)。
  • listdir 为您提供目录中唯一的文件名,有没有一种方法可以获取完整路径?
  • @greperror 您可以使用os.path.abspath 获取完整路径。此外,要检查给定路径是否为文件,请使用 os.path.isfileos.path.isdir
【解决方案2】:
import os

for filename in os.listdir("C:\\temp"):
    print  filename

【讨论】:

  • r'C:\temp'"C:\\temp" 更清晰,更适合使用原始字符串而不是转义反斜杠。
  • @smci:实际上"C:/temp" 是首选。
  • @martineau:没有达成共识;这就像emacs-vs-vi。正斜杠更可取,因为它不能被误解为转义字符,但反斜杠仍然更受欢迎......
  • @smci:正斜杠也是可移植的,不需要特殊前缀。我不会批评任何人像 OP 那样做。无论如何,就人气而言,我们必须在不同的圈子中移动。 ;¬)
【解决方案3】:

试试这个:

import os
for top, dirs, files in os.walk('./'):
    for nm in files:       
        print os.path.join(top, nm)

【讨论】:

  • 一行:[top + os.sep + f for top, dirs, files in os.walk('./') for f in files]
【解决方案4】:

这是一种遍历目录树中每个文件和目录的方法:

import os

for dirname, dirnames, filenames in os.walk('.'):
    # print path to all subdirectories first.
    for subdirname in dirnames:
        print(os.path.join(dirname, subdirname))

    # print path to all filenames.
    for filename in filenames:
        print(os.path.join(dirname, filename))

    # Advanced usage:
    # editing the 'dirnames' list will stop os.walk() from recursing into there.
    if '.git' in dirnames:
        # don't go into any .git directories.
        dirnames.remove('.git')

【讨论】:

  • 如果您从 Python Shell 运行此代码(按原样),请记住 Ctrl+C 将停止向所述 shell 的输出。 ;)
  • 这将递归地列出文件和目录
  • 您甚至可以编辑目录名列表以防止它沿某些路径递归。
  • @Clément "当 topdown 为 True 时,调用者可以就地修改 dirnames 列表(可能使用 del 或 slice 赋值),并且 walk() 只会递归到名称保留在 dirnames 中的子目录; 这可以用来修剪搜索,强加特定的访问顺序,甚至在调用者再次恢复 walk() 之前通知 walk() 有关调用者创建或重命名的目录。"来自docs.python.org/2/library/os.html#os.walk
  • 忽略某些目录的更简单方法是首先不将它们添加到目录名for subdirname in dirnames: if subdirname != '.git'
【解决方案5】:

这是我经常使用的辅助函数:

import os

def listdir_fullpath(d):
    return [os.path.join(d, f) for f in os.listdir(d)]

【讨论】:

  • 生成器会更好。
  • @RobertSiemer 取决于使用情况。在许多情况下,列表会更好,但我想生成器更通用,因为它可以转换为列表。这取决于您是在寻找多功能性还是更精简的东西。
  • 已经十年了,但我想我是这样做的,因为 os.listdir() 返回一个列表,我在模仿。
【解决方案6】:

我写了一个长版本,包含我可能需要的所有选项:http://sam.nipl.net/code/python/find.py

我想它也适合这里:

#!/usr/bin/env python

import os
import sys

def ls(dir, hidden=False, relative=True):
    nodes = []
    for nm in os.listdir(dir):
        if not hidden and nm.startswith('.'):
            continue
        if not relative:
            nm = os.path.join(dir, nm)
        nodes.append(nm)
    nodes.sort()
    return nodes

def find(root, files=True, dirs=False, hidden=False, relative=True, topdown=True):
    root = os.path.join(root, '')  # add slash if not there
    for parent, ldirs, lfiles in os.walk(root, topdown=topdown):
        if relative:
            parent = parent[len(root):]
        if dirs and parent:
            yield os.path.join(parent, '')
        if not hidden:
            lfiles   = [nm for nm in lfiles if not nm.startswith('.')]
            ldirs[:] = [nm for nm in ldirs  if not nm.startswith('.')]  # in place
        if files:
            lfiles.sort()
            for nm in lfiles:
                nm = os.path.join(parent, nm)
                yield nm

def test(root):
    print "* directory listing, with hidden files:"
    print ls(root, hidden=True)
    print
    print "* recursive listing, with dirs, but no hidden files:"
    for f in find(root, dirs=True):
        print f
    print

if __name__ == "__main__":
    test(*sys.argv[1:])

【讨论】:

    【解决方案7】:

    如果您需要通配能力,也可以使用一个模块。例如:

    import glob
    glob.glob('./[0-9].*')
    

    将返回类似:

    ['./1.gif', './2.txt']
    

    请参阅文档here

    【讨论】:

    • 这真是太棒了!你能在那些匹配的表达式中有否定吗?除了匹配 THIS 模式的文件之外的所有内容都喜欢吗?
    • @CharlieParker:你不能直接使用glob,但你可以很容易地使用它或os.listdir()re 正则表达式模块一起使用——请参阅this answer另一个问题。
    【解决方案8】:
    #import modules
    import os
    
    _CURRENT_DIR = '.'
    
    
    def rec_tree_traverse(curr_dir, indent):
        "recurcive function to traverse the directory"
        #print "[traverse_tree]"
    
        try :
            dfList = [os.path.join(curr_dir, f_or_d) for f_or_d in os.listdir(curr_dir)]
        except:
            print "wrong path name/directory name"
            return
    
        for file_or_dir in dfList:
    
            if os.path.isdir(file_or_dir):
                #print "dir  : ",
                print indent, file_or_dir,"\\"
                rec_tree_traverse(file_or_dir, indent*2)
    
            if os.path.isfile(file_or_dir):
                #print "file : ",
                print indent, file_or_dir
    
        #end if for loop
    #end of traverse_tree()
    
    def main():
    
        base_dir = _CURRENT_DIR
    
        rec_tree_traverse(base_dir," ")
    
        raw_input("enter any key to exit....")
    #end of main()
    
    
    if __name__ == '__main__':
        main()
    

    【讨论】:

    • 这个问题已经有了很好的答案,不用再回答了
    【解决方案9】:

    FYI 添加扩展名或 ext 文件的过滤器 导入操作系统

    path = '.'
    for dirname, dirnames, filenames in os.walk(path):
        # print path to all filenames with extension py.
        for filename in filenames:
            fname_path = os.path.join(dirname, filename)
            fext = os.path.splitext(fname_path)[1]
            if fext == '.py':
                print fname_path
            else:
                continue
    

    【讨论】:

      【解决方案10】:

      递归地仅列出文件的好方法。我在 setup.py package_data 指令中使用了它:

      import os
      
      [os.path.join(x[0],y) for x in os.walk('<some_directory>') for y in x[2]]
      

      我知道这不是问题的答案,但可能会派上用场

      【讨论】:

        【解决方案11】:

        递归实现

        import os
        
        def scan_dir(dir):
            for name in os.listdir(dir):
                path = os.path.join(dir, name)
                if os.path.isfile(path):
                    print path
                else:
                    scan_dir(path)
        

        【讨论】:

          【解决方案12】:

          如果我想我会把它扔进去。进行通配符搜索的简单而肮脏的方式。

          import re
          import os
          
          [a for a in os.listdir(".") if re.search("^.*\.py$",a)]
          

          【讨论】:

            【解决方案13】:

            对于当前工作目录中没有指定路径的文件

            Python 2.7:

            import os
            os.listdir('.')
            

            Python 3.x:

            import os
            os.listdir()
            

            【讨论】:

              【解决方案14】:

              对于 Python 2

              #!/bin/python2
              
              import os
              
              def scan_dir(path):
                  print map(os.path.abspath, os.listdir(pwd))
              

              对于 Python 3

              filter 和 map 需要用 list() 包裹起来

              #!/bin/python3
              
              import os
              
              def scan_dir(path):
                  print(list(map(os.path.abspath, os.listdir(pwd))))
              

              现在的建议是您使用生成器表达式或列表推导替换您对 map 和 filter 的使用:

              #!/bin/python
              
              import os
              
              def scan_dir(path):
                  print([os.path.abspath(f) for f in os.listdir(path)])
              

              【讨论】:

                【解决方案15】:

                下面的代码将列出目录和目录中的文件

                def print_directory_contents(sPath):
                        import os                                       
                        for sChild in os.listdir(sPath):                
                            sChildPath = os.path.join(sPath,sChild)
                            if os.path.isdir(sChildPath):
                                print_directory_contents(sChildPath)
                            else:
                                print(sChildPath)
                

                【讨论】:

                  【解决方案16】:

                  这是一个单行 Pythonic 版本:

                  import os
                  dir = 'given_directory_name'
                  filenames = [os.path.join(os.path.dirname(os.path.abspath(__file__)),dir,i) for i in os.listdir(dir)]
                  

                  此代码列出了给定目录名称中所有文件和目录的完整路径。

                  【讨论】:

                  • 谢谢萨利赫,但你的代码并没有完全运行,并且工作的一个被修改如下: 'dir = 'given_directory_name' filenames = [os.path.abspath(os.path.join( dir,i)) for i in os.listdir(dir)]'
                  【解决方案17】:

                  我知道这是一个老问题。如果您在 liunx 机器上,这是我遇到的一种巧妙方法。

                  import subprocess
                  print(subprocess.check_output(["ls", "/"]).decode("utf8"))
                  

                  【讨论】:

                  【解决方案18】:

                  和我一起工作的那个是本页其他地方萨利赫回答的修改版本。

                  代码如下:

                  dir = 'given_directory_name'
                  filenames = [os.path.abspath(os.path.join(dir,i)) for i in os.listdir(dir)]
                  

                  【讨论】:

                    【解决方案19】:

                    这是另一种选择。

                    os.scandir(path='.')
                    

                    它返回一个 os.DirEntry 对象的迭代器,该对象对应于 path 给定的目录中的条目(以及文件属性信息)。

                    例子:

                    with os.scandir(path) as it:
                        for entry in it:
                            if not entry.name.startswith('.'):
                                print(entry.name)
                    

                    使用 scandir() 代替 listdir() 可以显着提高还需要文件类型或文件属性信息的代码的性能,因为 os.DirEntry 对象会在操作系统提供时公开此信息扫描目录时。所有 os.DirEntry 方法都可以进行系统调用,但是 is_dir() 和 is_file() 通常只需要对符号链接进行系统调用; os.DirEntry.stat() 在 Unix 上总是需要一个系统调用,但在 Windows 上只需要一个用于符号链接。

                    Python Docs

                    【讨论】:

                      【解决方案20】:

                      虽然os.listdir() 可以很好地生成文件和目录名称的列表,但是一旦有了这些名称,您通常会想要做更多的事情——而在 Python3 中,pathlib 使其他杂务变得简单。让我们来看看你是否和我一样喜欢它。

                      要列出目录内容,构造一个 Path 对象并获取迭代器:

                      In [16]: Path('/etc').iterdir()
                      Out[16]: <generator object Path.iterdir at 0x110853fc0>
                      

                      如果我们只想要事物名称的列表:

                      In [17]: [x.name for x in Path('/etc').iterdir()]
                      Out[17]:
                      ['emond.d',
                       'ntp-restrict.conf',
                       'periodic',
                      

                      如果你只想要目录:

                      In [18]: [x.name for x in Path('/etc').iterdir() if x.is_dir()]
                      Out[18]:
                      ['emond.d',
                       'periodic',
                       'mach_init.d',
                      

                      如果您想要该树中所有 conf 文件的名称:

                      In [20]: [x.name for x in Path('/etc').glob('**/*.conf')]
                      Out[20]:
                      ['ntp-restrict.conf',
                       'dnsextd.conf',
                       'syslog.conf',
                      

                      如果您想要树中的 conf 文件列表 >= 1K:

                      In [23]: [x.name for x in Path('/etc').glob('**/*.conf') if x.stat().st_size > 1024]
                      Out[23]:
                      ['dnsextd.conf',
                       'pf.conf',
                       'autofs.conf',
                      

                      解析相对路径变得容易:

                      In [32]: Path('../Operational Metrics.md').resolve()
                      Out[32]: PosixPath('/Users/starver/code/xxxx/Operational Metrics.md')
                      

                      使用路径导航非常清晰(尽管出乎意料):

                      In [10]: p = Path('.')
                      
                      In [11]: core = p / 'web' / 'core'
                      
                      In [13]: [x for x in core.iterdir() if x.is_file()]
                      Out[13]:
                      [PosixPath('web/core/metrics.py'),
                       PosixPath('web/core/services.py'),
                       PosixPath('web/core/querysets.py'),
                      

                      【讨论】:

                        猜你喜欢
                        • 2020-03-22
                        • 2019-04-23
                        • 2012-04-01
                        • 2022-06-15
                        • 2021-02-17
                        • 2014-02-02
                        • 1970-01-01
                        • 1970-01-01
                        相关资源
                        最近更新 更多