如何在Python中列出目录中的所有文件并将其添加到列表中?


import os
os.listdir("somedirectory")

将返回“somedirectory”中所有文件和目录的列表。


listdir()返回目录中的所有内容——包括文件和目录。

os.path的isfile()只能用于列出文件:

from os import listdir
from os.path import isfile, join
onlyfiles = [f for f in listdir(mypath) if isfile(join(mypath, f))]

或者,os.walk()为它访问的每个目录生成两个列表——一个用于文件,一个用于目录。如果您只想要顶级目录,则可以在第一次生成时中断:

from os import walk

f = []
for (dirpath, dirnames, filenames) in walk(mypath):
    f.extend(filenames)
    break

或更短:

from os import walk

filenames = next(walk(mypath), (None, None, []))[2]  # [] if no file

我更喜欢使用glob模块,因为它可以进行模式匹配和扩展。

import glob
print(glob.glob("/home/adam/*"))

它可以直观地进行模式匹配

import glob
# All files and directories ending with .txt and that don't begin with a dot:
print(glob.glob("/home/adam/*.txt")) 
# All files and directories ending with .txt with depth of 2 folders, ignoring names beginning with a dot:
print(glob.glob("/home/adam/*/*.txt")) 

它将返回一个包含查询文件和目录的列表:

['/home/adam/file1.txt', '/home/adam/file2.txt', .... ]

注意,glob忽略以点开头的文件和目录。,因为这些被认为是隐藏的文件和目录,除非模式类似于.*。

使用glob.escape转义不应该是模式的字符串:

print(glob.glob(glob.escape(directory_name) + "/*.txt"))

dircache是“自2.6版以来已弃用:Python 3.0中已删除dircache模块。”

import dircache
list = dircache.listdir(pathname)
i = 0
check = len(list[0])
temp = []
count = len(list)
while count != 0:
  if len(list[i]) != check:
     temp.append(list[i-1])
     check = len(list[i])
  else:
    i = i + 1
    count = count - 1

print temp

从目录及其所有子目录获取完整文件路径

import os

def get_filepaths(directory):
    """
    This function will generate the file names in a directory 
    tree by walking the tree either top-down or bottom-up. For each 
    directory in the tree rooted at directory top (including top itself), 
    it yields a 3-tuple (dirpath, dirnames, filenames).
    """
    file_paths = []  # List which will store all of the full filepaths.

    # Walk the tree.
    for root, directories, files in os.walk(directory):
        for filename in files:
            # Join the two strings in order to form the full filepath.
            filepath = os.path.join(root, filename)
            file_paths.append(filepath)  # Add it to the list.

    return file_paths  # Self-explanatory.

# Run the above function and store its results in a variable.   
full_file_paths = get_filepaths("/Users/johnny/Desktop/TEST")

我在上述函数中提供的路径包含3个文件,其中两个位于根目录中,另一个位于名为“subfolder”的子文件夹中打印将打印列表的完整文件路径:['/Users/johnny/Desktop/TEST/file1.txt','/Users/johnny/Desctop/TEST-file2.txt','/Users/johnny/Desktop/STEST/SUBFOLDER/file3.dat']

如果愿意,您可以打开并阅读内容,或者只关注扩展名为“.dat”的文件,如下面的代码所示:

for f in full_file_paths:
  if f.endswith(".dat"):
    print f

/用户/johnny/Desktop/TEST/SUBFOLDER/file3.dat


仅获取文件列表(无子目录)的单行解决方案:

filenames = next(os.walk(path))[2]

或绝对路径名:

paths = [os.path.join(path, fn) for fn in next(os.walk(path))[2]]

如果您正在寻找find的Python实现,这是我经常使用的方法:

from findtools.find_files import (find_files, Match)

# Recursively find all *.sh files in **/usr/bin**
sh_files_pattern = Match(filetype='f', name='*.sh')
found_files = find_files(path='/usr/bin', match=sh_files_pattern)

for found_file in found_files:
    print found_file

所以我用它制作了一个PyPI包,还有一个GitHub存储库。我希望有人发现它对这段代码可能有用。


def list_files(path):
    # returns a list of names (with extension, without full path) of all files 
    # in folder path
    files = []
    for name in os.listdir(path):
        if os.path.isfile(os.path.join(path, name)):
            files.append(name)
    return files 

返回绝对文件路径列表,不会递归到子目录

L = [os.path.join(os.getcwd(),f) for f in os.listdir('.') if os.path.isfile(os.path.join(os.getcwd(),f))]

我真的很喜欢adamk的回答,建议您使用来自同名模块的glob()。这允许您使用*s进行模式匹配。

但正如其他人在评论中指出的,glob()可能会被不一致的斜线方向绊倒。为了帮助实现这一点,我建议您在os.path模块中使用join()和expanduser()函数,也可以在os模块中使用getcwd()函数。

例如:

from glob import glob

# Return everything under C:\Users\admin that contains a folder called wlp.
glob('C:\Users\admin\*\wlp')

上面的情况很糟糕-路径已被硬编码,并且只能在Windows上在驱动器名称和硬编码到路径之间工作。

from glob    import glob
from os.path import join

# Return everything under Users, admin, that contains a folder called wlp.
glob(join('Users', 'admin', '*', 'wlp'))

上面的方法效果更好,但它依赖于文件夹名Users,该文件夹名在Windows中常见,而在其他操作系统中不常见。它还依赖于具有特定名称admin的用户。

from glob    import glob
from os.path import expanduser, join

# Return everything under the user directory that contains a folder called wlp.
glob(join(expanduser('~'), '*', 'wlp'))

这在所有平台上都非常有效。

另一个很好的例子,它可以在不同的平台上完美运行,并且做了一些不同的事情:

from glob    import glob
from os      import getcwd
from os.path import join

# Return everything under the current directory that contains a folder called wlp.
glob(join(getcwd(), '*', 'wlp'))

希望这些示例能帮助您了解在标准Python库模块中可以找到的一些函数的功能。


从3.4版开始,有内置的迭代器,比os.listdir()高效得多:

pathlib:3.4版新增。

>>> import pathlib
>>> [p for p in pathlib.Path('.').iterdir() if p.is_file()]

根据PEP428,pathlib库的目的是提供一个简单的类层次结构来处理文件系统路径和用户对它们进行的常见操作。

os.scandir():3.5版新增。

>>> import os
>>> [entry for entry in os.scandir('.') if entry.is_file()]

注意,os.walk()使用os.scandir()而不是3.5版的os.listdir(),根据PEP471,它的速度提高了2-20倍。

让我也推荐阅读ShadowRanger在下面的评论。


使用发电机

import os
def get_files(search_path):
     for (dirpath, _, filenames) in os.walk(search_path):
         for filename in filenames:
             yield os.path.join(dirpath, filename)
list_files = get_files('.')
for filename in list_files:
    print(filename)

当前目录中的列表

使用os模块中的listdir,可以获得当前目录中的文件和文件夹

import os

arr = os.listdir()

查找目录

arr = os.listdir('c:\\files')

使用glob,可以指定要列出的文件类型,如下所示

import glob

txtfiles = []
for file in glob.glob("*.txt"):
    txtfiles.append(file)

or

mylist = [f for f in glob.glob("*.txt")]

仅获取当前目录中文件的完整路径

import os
from os import listdir
from os.path import isfile, join

cwd = os.getcwd()
onlyfiles = [os.path.join(cwd, f) for f in os.listdir(cwd) if 
os.path.isfile(os.path.join(cwd, f))]
print(onlyfiles) 

['G:\\getfilesname\\getfilesname.py', 'G:\\getfilesname\\example.txt']

使用os.path.abspath获取完整路径名

你得到了完整的路径作为回报

 import os
 files_path = [os.path.abspath(x) for x in os.listdir()]
 print(files_path)
 
 ['F:\\documenti\applications.txt', 'F:\\documenti\collections.txt']

漫游:遍历子目录

os.walk返回根目录、目录列表和文件列表,这就是为什么我在for循环中在r、d、f中解压缩它们;然后,它在根目录的子文件夹中查找其他文件和目录,依此类推,直到没有子文件夹为止。

import os

# Getting the current work directory (cwd)
thisdir = os.getcwd()

# r=root, d=directories, f = files
for r, d, f in os.walk(thisdir):
    for file in f:
        if file.endswith(".docx"):
            print(os.path.join(r, file))

在目录树中向上

# Method 1
x = os.listdir('..')

# Method 2
x= os.listdir('/')

使用os.listdir()获取特定子目录的文件

import os

x = os.listdir("./content")

os.walk('.')-当前目录

 import os
 arr = next(os.walk('.'))[2]
 print(arr)
 
 >>> ['5bs_Turismo1.pdf', '5bs_Turismo1.pptx', 'esperienza.txt']

next(os.walk('.'))和os.path.join('dir','file')

 import os
 arr = []
 for d,r,f in next(os.walk("F:\\_python")):
     for file in f:
         arr.append(os.path.join(r,file))

 for f in arr:
     print(files)

>>> F:\\_python\\dict_class.py
>>> F:\\_python\\programmi.txt

下一个步行

 [os.path.join(r,file) for r,d,f in next(os.walk("F:\\_python")) for file in f]
 
 >>> ['F:\\_python\\dict_class.py', 'F:\\_python\\programmi.txt']

os.walk

x = [os.path.join(r,file) for r,d,f in os.walk("F:\\_python") for file in f]
print(x)

>>> ['F:\\_python\\dict.py', 'F:\\_python\\progr.txt', 'F:\\_python\\readl.py']

os.listdir()-仅获取txt文件

 arr_txt = [x for x in os.listdir() if x.endswith(".txt")]
 

使用glob获取文件的完整路径

from path import path
from glob import glob

x = [path(f).abspath() for f in glob("F:\\*.txt")]

使用os.path.isfile避免列表中的目录

import os.path
listOfFiles = [f for f in os.listdir() if os.path.isfile(f)]

使用Python 3.4中的pathlib

import pathlib

flist = []
for p in pathlib.Path('.').iterdir():
    if p.is_file():
        print(p)
        flist.append(p)

通过列表理解:

flist = [p for p in pathlib.Path('.').iterdir() if p.is_file()]

在pathlib.Path()中使用glob方法

import pathlib

py = pathlib.Path().glob("*.py")

使用os.walk获取所有文件:仅检查返回的第三个元素,即文件列表

import os
x = [i[2] for i in os.walk('.')]
y=[]
for t in x:
    for f in t:
        y.append(f)

仅获取目录中带有next的文件:仅返回根文件夹中的文件

 import os
 x = next(os.walk('F://python'))[2]

使用next只获取目录并在目录中行走,因为在[1]元素中只有文件夹

 import os
 next(os.walk('F://python'))[1] # for the current dir use ('.')
 
 >>> ['python3','others']

使用walk获取所有分区名称

for r,d,f in os.walk("F:\\_python"):
    for dirs in d:
        print(dirs)

Python 3.5及更高版本的os.scandir()

import os
x = [f.name for f in os.scandir() if f.is_file()]

# Another example with `scandir` (a little variation from docs.python.org)
# This one is more efficient than `os.listdir`.
# In this case, it shows the files only in the current directory
# where the script is executed.

import os
with os.scandir() as i:
    for entry in i:
        if entry.is_file():
            print(entry.name)

这是我的通用函数。它返回文件路径列表而不是文件名,因为我发现这更有用。它有几个可选的参数,使其具有通用性。例如,我经常将其与pattern=“*.txt”或subfolders=True等参数一起使用。

import os
import fnmatch

def list_paths(folder='.', pattern='*', case_sensitive=False, subfolders=False):
    """Return a list of the file paths matching the pattern in the specified 
    folder, optionally including files inside subfolders.
    """
    match = fnmatch.fnmatchcase if case_sensitive else fnmatch.fnmatch
    walked = os.walk(folder) if subfolders else [next(os.walk(folder))]
    return [os.path.join(root, f)
            for root, dirnames, filenames in walked
            for f in filenames if match(f, pattern)]

我将提供一个示例单行,其中可以提供源路径和文件类型作为输入。代码返回带有csv扩展名的文件名列表。使用以防需要返回所有文件。这还将递归扫描子目录。

[y代表os.walk中的x(sourcePath)代表glob中的y(os.path.join(x[0],'*.csv'))]

根据需要修改文件扩展名和源路径。


初步说明

尽管问题文本中的文件和目录术语有明显的区别,但有些人可能会认为目录实际上是特殊的文件语句:“目录的所有文件”可以用两种方式解释:仅所有直接(或级别1)后代整个目录树中的所有子体(包括子目录中的子体)当问到这个问题时,我认为Python 2是LTS版本,但是代码示例将由Python 3(.5)运行(我将尽可能保持它们与Python 2兼容;此外,我将发布的任何属于Python的代码都来自v3.5.4,除非另有规定)。这会产生与问题中的另一个关键词相关的后果:“将它们添加到列表中”:在Python 2.2之前的版本中,序列(可迭代)主要由列表(元组、集合…)表示在Python2.2中,引入了生成器([Python.Wiki]:生成器)的概念-由[Python.Docs]提供:简单语句-yield语句)。随着时间的推移,返回/处理列表的函数开始出现生成器对应项在Python 3中,生成器是默认行为不确定返回列表是否仍然是必需的(或者生成器也会这样做),但将生成器传递给列表构造函数将从中创建列表(并使用它)。下面的示例说明了[Python.Docs]上的差异:内置函数-map(function,iterable,*iterables)>>>导入系统>>>>>>系统版本'2.7.10(默认值,2016年3月8日,15:02:46)[MSC v.1600 64位(AMD64)]'>>>m=map(lambda x:x,[1,2,3])#只是一个伪lambda函数>>>m,类型(m)([1,2,3],<type'list'>)>>>长度(m)3.>>>导入系统>>>>>>系统版本“3.5.4(v3.5.4:3f56838,2017年8月8日,02:17:05)[MSC v.1900 64位(AMD64)]”>>>m=映射(λx:x,[1,2,3])>>>m,类型(m)(<映射对象位于0x000001B4257342B0>,<class‘map‘>)>>>长度(m)回溯(最近一次调用):文件“<stdin>”,第1行,在<module>中TypeError:“map”类型的对象没有len()>>>lm0=list(m)#从生成器生成列表>>>lm0,类型(lm0)([1,2,3],<class'list'>)>>>>>>lm1=list(m)#从同一生成器生成列表>>>lm1,type(lm1)#现在清空列表-生成器已耗尽([],<class'list'>)这些示例将基于一个名为root_dir的目录,其结构如下(此示例适用于Win,但我也在Nix上使用相同的树)。注意,我将重用控制台:[cfati@CFATI-5510-0:e:\Work\Dev\StackOverflow\q003207219]>sop.bat###设置较短的提示,以便粘贴到StackOverflow(或其他)页面时更适合###[提示]>[提示]>tree/f“root_dir”卷Work的文件夹PATH列表卷序列号为00000029 3655:6FDE: \WORK\DEV\STACKOVERFLOW\Q003207219\ROOT_DIR¦文件0¦文件1¦+---目录0¦+---dir00¦¦¦file000¦ ¦ ¦¦¦+---dir000¦¦文件0000¦ ¦¦+---方向01¦¦文件010¦¦文件011¦ ¦¦+---方向02¦+---方向020¦+---方向0200+---目录1¦文件10¦文件11¦文件12¦+---目录2¦¦文件20¦ ¦¦+---方向20¦文件200¦+---目录3


解决

程序化方法

1.[Python.Docs]:os.listdir(路径=“.”)

返回一个列表,其中包含按路径给定的目录中的条目名称。列表按任意顺序排列,不包括特殊条目“”和“..”。。。


>>>导入操作系统>>>>>>root_dir=“root_dir”#相对于当前目录的路径(os.getcwd())>>>>>>os.listdir(root_dir)#列出root_dir中的所有项['dir0','dir1','dir 2','diri3','file0','file 1']>>>>>>[如果os.path.isfile(os.path.jjoin(root_dir,item)),则os.listdir(root_dr)中的item for item]#过滤项目并仅保留文件(删除目录)[“文件0”,“文件1”]

更详细的示例(code_os_listdir.py):

#!/usr/bin/env python

import os
import sys
from pprint import pformat as pf


def _get_dir_content(path, include_folders, recursive):
    entries = os.listdir(path)
    for entry in entries:
        entry_with_path = os.path.join(path, entry)
        if os.path.isdir(entry_with_path):
            if include_folders:
                yield entry_with_path
            if recursive:
                for sub_entry in _get_dir_content(entry_with_path, include_folders, recursive):
                    yield sub_entry
        else:
            yield entry_with_path


def get_dir_content(path, include_folders=True, recursive=True, prepend_folder_name=True):
    path_len = len(path) + len(os.path.sep)
    for item in _get_dir_content(path, include_folders, recursive):
        yield item if prepend_folder_name else item[path_len:]


def _get_dir_content_old(path, include_folders, recursive):
    entries = os.listdir(path)
    ret = list()
    for entry in entries:
        entry_with_path = os.path.join(path, entry)
        if os.path.isdir(entry_with_path):
            if include_folders:
                ret.append(entry_with_path)
            if recursive:
                ret.extend(_get_dir_content_old(entry_with_path, include_folders, recursive))
        else:
            ret.append(entry_with_path)
    return ret


def get_dir_content_old(path, include_folders=True, recursive=True, prepend_folder_name=True):
    path_len = len(path) + len(os.path.sep)
    return [item if prepend_folder_name else item[path_len:] for item in _get_dir_content_old(path, include_folders, recursive)]


def main(*argv):
    root_dir = "root_dir"
    ret0 = get_dir_content(root_dir, include_folders=True, recursive=True, prepend_folder_name=True)
    lret0 = list(ret0)
    print("{:} {:d}\n{:s}".format(ret0, len(lret0), pf(lret0)))
    ret1 = get_dir_content_old(root_dir, include_folders=False, recursive=True, prepend_folder_name=False)
    print("\n{:d}\n{:s}".format(len(ret1), pf(ret1)))


if __name__ == "__main__":
    print("Python {:s} {:03d}bit on {:s}\n".format(" ".join(elem.strip() for elem in sys.version.split("\n")),
                                                   64 if sys.maxsize > 0x100000000 else 32, sys.platform))
    rc = main(*sys.argv[1:])
    print("\nDone.\n")
    sys.exit(rc)

笔记:

有两种实现方式:一种使用生成器的方法(当然,这里似乎没有用,因为我立即将结果转换为列表)经典的(函数名以_old结尾)使用递归(进入子目录)对于每个实现,有两个功能:以下划线(_)开头的一个:“private”(不应直接调用)-完成所有工作公共路径(前一个的包装器):它只是从返回的条目中剥离初始路径(如果需要)。这是一个丑陋的实现,但这是我目前唯一能想到的想法就性能而言,生成器通常会快一点(考虑到创建和迭代时间),但我没有在递归函数中测试它们,而且我还在函数内部迭代内部生成器-不知道这对性能有多友好玩弄争论以获得不同的结果

输出:

[提示]>“e:\Work\Dev\VEnvs\py_pc064_03.05.04_test0\Scripts\python.exe”“.\code_os_listdir.py”Python 3.5.4(v3.5.4:3f56838,2017年8月8日,02:17:05)[MSC v.1900 64位(AMD64)]win32上的064bit<0x000002C080418F68处的生成器对象get_dir_content>22['root_dir\\dir0','root_dir\\dir0\\dir00','root_dir\\dir0\\dir00\\dir000',“root_dir\\dir0\\dir00\\dir000\\file0000”,'root_dir\\dir0\\dir00\\file000',“root_dir\\dir0\\dir01”,“root_dir\\dir0\\dir01\\file010”,“root_dir\\dir0\\dir01\\file011”,'root_dir\\dir0\\dir02',“root_dir\\dir0\\dir02\\dir020”,“root_dir\\dir0\\dir02\\dir020\\dir0200”,'root_dir\\dir1','root_dir\\dir1\\file10','root_dir\\dir1\\file11','root_dir\\dir1\\file12','root_dir\\dir2','root_dir\\dir2\\dir20','root_dir\\dir2\\dir20\\file200','root_dir\\dir2\\file20','root_dir\\dir3',“root_dir\\file0”,'root_dir\\file1']11['dir0\\dir00\\dir000\\file0000','dir0\\dir00\\file000',“dir0\\dir01\\file010”,“dir0\\dir01\\file011”,'dir1\\file10','dir1\\file11','dir1\\file12','dir2\\dir20\\file200','dir2\\file20',“文件0”,'文件1']完成。

2.[Python.Docs]:os.scandir(路径=“.”)

仅在Python 3.5+中,backport:[PyPI]:scandir:

返回一个os.DirEntry对象的迭代器,这些对象对应于路径给定的目录中的条目。条目按任意顺序生成,特殊条目“.”和“..”不包括在内。使用scandir()而不是listdir()可以显著提高同样需要文件类型或文件属性信息的代码的性能,因为os.DirEntry对象在扫描目录时如果操作系统提供了这些信息,就会暴露这些信息。所有os.DirEntry方法都可以执行系统调用,但is_dir()和is_file()通常只需要对符号链接进行系统调用;os.DirEntry.stat()在Unix上总是需要一个系统调用,但在Windows上只需要一个符号链接。


>>>导入操作系统>>>>>>root_dir=os.path.join(“.”,“root_dir”)#明确地在当前目录前面加上前缀>>>根目录(_D)'.\\根目录'>>>>>>scandir_iterator=os.scandir(root_dir)>>>斯堪的纳维亚人<nt.ScandirIterator对象位于0x00000268CF4BC140>>>>[scandir_iterator中项目的item.path]['.\\root_dir\\dir0','.\\root_dir\\dir 1','.\\root_dir\\ dir2','..\\root_dir \\dir3','./\root_dir \\ file0',''.\\root-dir\\file1']>>>>>>[scandir_iterator]中的item.path#将产生一个空列表,因为它被上一次迭代使用(由列表理解自动执行)[]>>>>>>scandir_iterator=os.scandir(root_dir)#重新初始化生成器>>>对于scandir_iterator中的项目:…如果os.path.isfile(item.path):…打印(项目名称)...文件0文件1

笔记:

类似于os.listdir但它也更灵活(并提供更多功能),更具Python风格(在某些情况下,速度更快)

3.[Python.Docs]:os.walk(top,topdown=True,oneror=None,followlinks=False)

通过自上而下或自下而上遍历目录树,在目录树中生成文件名。对于树中以目录顶端为根的每个目录(包括顶端本身),它生成一个三元组(目录路径、目录名、文件名)。


>>>导入操作系统>>>>>>root_dir=os.path.join(os.getcwd(),“root_dir”)#指定完整路径>>>根目录(_D)'E:\\Work\\Dev\\StackOverflow\\q003207219\\root_dir'>>>>>>walk_generator=os.walk(root_dir)>>>root_dir_intry=next(walk_generator)#第一个条目对应于根目录(作为参数传递)>>>根目录条目('E:\\Work\\Dev\\StackOverflow\\q003207219\\root_dir',['dir0','dir1','dir 2','diri3'],['file0','file1'])>>>>>>root_dir_entry[1]+root_dir_intry[2]#在单个列表中显示目录和文件(直系后代)['dir0','dir1','dir 2','diri3','file0','file 1']>>>>>>[os.path.join(root_dir_entry[0],item)for root_dir_intry[1]+root_dir-entry[2]中的项]#按完整路径显示前一列表中的所有项['E:\\Work\\Dev\\StackOverflow\\q003207219\\root_dir\\dir0','E:\\Work\\Dev\\StarkOverflow\\ q003207219 \\root_dir \\dir1','A:\\Work\\ Dev\\Stack Overflow\\q003207219\\ root_dir \\ dir2','E:\\Work\\Dev\\ StackOverview\\q003207 219\\root-dir\\dir3','E:\\Work\\Def\\StackOverflow\\q002207219\\root_dir\\file0','E:\\Work\\Dev\\StackOverflow\\q003207219\\root_dir\\file1']>>>>>>for walk_generator中的条目:#显示其余元素(对应于每个子分区)…打印(条目)...('E:\\Work\\Dev\\StackOverflow\\q003207219\\root_dir\\dir0',['dir00','dir01','dir02'],[])('E:\\Work\\Dev\\StackOverflow\\q003207219\\root_dir\\dir0\\dir00',['dir000'],['file000'])('E:\\Work\\Dev\\StackOverflow\\q003207219\\root_dir\\dir0\\dir00\\dir000',[],['file0000'])('E:\\Work\\Dev\\StackOverflow\\q003207219\\root_dir\\dir0\\dir01',[],['file010','file011'])('E:\\Work\\Dev\\StackOverflow\\q003207219\\root_dir\\dir0\\dir02',['dir020'],[])('E:\\Work\\Dev\\StackOverflow\\q003207219\\root_dir\\dir0\\dir02\\dir020',['dir0200'],[])('E:\\Work\\Dev\\StackOverflow\\q003207219\\root_dir\\dir0\\dir02\\dir020\\dir0200',[],[])('E:\\Work\\Dev\\StackOverflow\\q003207219\\root_dir\\dir1',[],['file10','file11','file 12'])('E:\\Work\\Dev\\StackOverflow\\q003207219\\root_dir\\dir2',['dir20'],['file20'])('E:\\Work\\Dev\\StackOverflow\\q003207219\\root_dir\\dir2\\dir20',[],['file200'])('E:\\Work\\Dev\\StackOverflow\\q003207219\\root_dir\\dir3',[],[])

笔记:

在场景下,它使用os.scandir(旧版本(Python)上的os.listdir)它通过在子文件夹中重复来完成繁重的工作

4.[Python.Docs]:glob.glob(路径名,*,root_dir=无,dir_fd=无,递归=假,include_hinded=假)

或glob.iglob:

返回与路径名匹配的路径名的可能为空的列表,该列表必须是包含路径规范的字符串。路径名可以是绝对的(如/usr/src/Python-1.5/Makefile)或相对的(如../../Tools/*/*.gif),并且可以包含shell样式的通配符。断开的符号链接包含在结果中(如外壳中)。。。。在3.5版中更改:支持使用“**”的递归globs。


>>>导入glob,os>>>>>>通配符模式=“*”>>>root_dir=os.path.join(“root_dir”,通配符模式)#匹配每个文件/目录名>>>根目录(_D)'root_dir\\*'>>>>>>glob_list=glob.glob(root_dir)>>>glob_list(全局列表)['root_dir\\dir0','root_dir \\dir1','root _dir\\dir 2','root_dir \\dir 3','oot_dir \\file0','root_dir \\ file1']>>>>>>[item.replace(“root_dir”+os.path.sep,“”)for glob_list中的项]#从开始处去掉目录名和路径分隔符['dir0','dir1','dir 2','diri3','file0','file 1']>>>>>>对于glob.iglob中的条目(root_dir+“*”,递归=True):…打印(条目)...根目录(_D)\根目录\目录0根目录\dir0\dir00根目录\dir0\dir00\dir000root_dir\dir0\dir00\dir000\file0000root_dir\dir0\dir00\file000根目录\dir0\dir01root_dir\dir0\dir01\file010根目录\dir0\dir01\file011根目录\dir0\dir02根目录\dir0\dir02\dir020根目录\dir0\dir02\dir020\dir0200根目录\目录1根目录\dir1\file10根目录\dir1\file11根目录\dir1\file12根目录\目录2根目录\dir2\dir20root_dir\dir2\dir20\file200根目录\dir2\file20根目录\目录3根目录\文件0根目录\文件1

笔记:

使用os.listdir对于大型树(尤其是在启用递归时),首选iglob允许基于名称的高级筛选(由于通配符)

5.[Python.Docs]:类pathlib.Path(*路径段)

Python 3.4+,backport:[PyPI]:pathlib2。

>>>导入路径库>>>>>>root_dir=“root_dir”>>>root_dir_instance=路径库路径(root_dir)>>>根目录实例Windows路径('root_dir')>>>根目录实例名称'根目录'>>>root_dir_instance.is_dir()真的>>>>>>[root_dir_instance.glob(“*”)中项目的item.name]#通配符搜索所有直接子项['dir0','dir1','dir 2','diri3','file0','file 1']>>>>>>如果不是item.is_dir(),则root_dir_instance.glob(“*”)中的项的os.parent.join(item.parent.name,item.name)]#仅显示文件的路径(包括父项)['root_dir\\file0','root_dir \\file1']

笔记:

这是实现我们目标的一种方式这是OOP风格的处理路径提供大量功能

6.[Python 2.Docs]:dircache.listdir(路径)

仅Python 2但是,根据[GitHub]:python/cpython-(2.7)cpython/Lib/dircache.py,它只是os.listdir上的一个带有缓存的(薄)包装器


def listdir(路径):“”“使用缓存列出目录内容。”“”尝试:cached_mtime,列表=缓存[路径]del缓存[路径]除了KeyError:cached_mtime,列表=-1,[]mtime=os.stat(路径).st_time如果mtime!=cached_mtime(缓存时间):list=os.listdir(路径)list.sort()cache[path]=mtime,列表返回列表

7.本机OS API

POSIX特定:

[Man7]:打开(3)[Man7]:读取指令(3)[Man7]:结束(3)

通过[Python.Docs]提供:ctypes-Python的外部函数库:

ctypes是Python的外部函数库。它提供与C兼容的数据类型,并允许调用DLL或共享库中的函数。它可以用来用纯Python包装这些库。

不直接相关,但请检查[SO]:在使用ctypes之前,通过ctypes从Python调用的C函数返回错误的值(@CristiFati的答案)。

代码_类型.py:

#!/usr/bin/env python3

import ctypes as cts
import sys


DT_DIR = 4
DT_REG = 8


class NixDirent64(cts.Structure):
    _fields_ = (
        ("d_ino", cts.c_ulonglong),
        ("d_off", cts.c_longlong),
        ("d_reclen", cts.c_ushort),
        ("d_type", cts.c_ubyte),
        ("d_name", cts.c_char * 256),
    )

NixDirent64Ptr = cts.POINTER(NixDirent64)


libc = this_process = cts.CDLL(None, use_errno=True)

opendir = libc.opendir
opendir.argtypes = (cts.c_char_p,)
opendir.restype = cts.c_void_p
readdir = libc.readdir
readdir.argtypes = (cts.c_void_p,)
readdir.restype = NixDirent64Ptr
closedir = libc.closedir
closedir.argtypes = (cts.c_void_p,)


def get_dir_content(path):
    ret = [path, [], []]
    pdir = opendir(cts.create_string_buffer(path.encode()))
    if not pdir:
        print("opendir returned NULL (errno: {:d})".format(cts.get_errno()))
        return ret
    cts.set_errno(0)
    while True:
        pdirent = readdir(pdir)
        if not pdirent:
            break
        dirent = pdirent.contents
        name = dirent.d_name.decode()
        if dirent.d_type & DT_DIR:
            if name not in (".", ".."):
                ret[1].append(name)
        elif dirent.d_type & DT_REG:
            ret[2].append(name)
    if cts.get_errno():
        print("readdir returned NULL (errno: {:d})".format(cts.get_errno()))
    closedir(pdir)
    return ret


def main(*argv):
    root_dir = "root_dir"
    entries = get_dir_content(root_dir)
    print("Entries:\n{:}".format(entries))


if __name__ == "__main__":
    print("Python {:s} {:03d}bit on {:s}\n".format(" ".join(elem.strip() for elem in sys.version.split("\n")),
                                                   64 if sys.maxsize > 0x100000000 else 32, sys.platform))
    rc = main(*sys.argv[1:])
    print("\nDone.\n")
    sys.exit(rc)

笔记:

它从LibC加载三个函数(LibC.so-在当前进程中加载)并调用它们(有关更多详细信息,请检查[so]:如何检查文件是否无异常存在NixDirent64是我的Ubuntu操作系统[Man7]:dirent.h(0P)中structdirent64的CTypes表示(DT_常量也是如此)。在其他风格/版本上,结构定义可能有所不同,如果是这样,则应更新CTypes别名,否则将产生未定义的行为它以os.walk的格式返回数据。我没有费心使其递归,但从现有代码开始,这将是一项相当简单的任务在Win上一切都是可行的,数据(库、函数、结构、常量……)不同

输出:

[cfati@cfati-5510-0:/mnt/e/Work/Dev/StackOverflow/q003207219]>python3.5./code_ctypes.pyPython 3.5.10(默认,2022年1月15日,19:53:00)[GCC 9.3.0]linux上的064bit条目:['root_dir',['dir0','dir1','dir2','dir3'],['file0','file1']]完成。

8.[TimGolden]:win32file.FindFilesW

特定于获胜:

使用Windows Unicode API检索匹配文件名的列表。API FindFirstFileW/FindNextFileW/Findclose函数的接口。


>>>导入操作系统,win32file作为wfile,win32con作为wcon>>>>>>root_dir=“root_dir”>>>root_dir通配符=os.path.join(root_dir,“*”)>>>entry_list=wfile.FindFilesW(root_dir_w通配符)>>>len(entry_list)#不要显示整个内容,因为它太长8.>>>[entry[-2]for entry_list]#仅显示条目名称[“.”、“..”、“dir0”、“dir1”、“dir2”、“dir 3”、“file0”、”file1“]>>>>>>如果条目[0]&wcon.FILE_ATTRIBUTE_DIRECTORY和条目[-2]不在(“.”,“..”)中,则为entry_list中的条目[条目[-2]]#筛选条目并仅显示目录名称(除了自身和父项)['dir0','dir1','dir 2','dir3']>>>>>>如果条目[0]&(wcon.FILE_ATTRIBUTE_NORMAL|wcon.FILE.ATTRIBUTE ARCHIVE)]#只显示文件的“完整”名称['root_dir\\file0','root_dir \\file1']

笔记:

win32file.FindFilesW是[GitHub]:mhammad/pywin32-Python for Windows(pywin32)扩展的一部分,它是WinAPI上的Python包装

9.使用一些(其他)第三方软件包

最有可能的是,将依赖于上述一项(或多项)(可能有轻微的定制)。

笔记:

代码是指可移植的(针对特定区域的地方除外-标记)或交叉:操作系统(Nix、Win、)Python版本(2、3、)在上述变体中使用了多种路径样式(绝对路径样式、相对路径样式),以说明所使用的“工具”在这个方向上是灵活的os.listdir和os.scandir使用opendir/readdir/closdir([MS.Learn]:FindFirstFileW函数(fileapi.h)/[MS.Learn]:FindNextFileW函数win32file.FindFilesW也使用这些(Win特定)函数(通过[GitHub]:mhammad/pywin32-(main)pywin32/win32/src/win32file.i)_get_dircontent(从第1点开始)可以使用这些方法中的任何一种实现(有些需要更多的工作,有些需要更少的工作)可以执行一些高级过滤(而不仅仅是文件与目录):例如,include_folders参数可以被另一个参数(例如,filter_func)替换,这是一个以路径为参数的函数:filter_func=lambda x:True(这不会删除任何内容),而在_get_dir_content中类似:如果不是filter_fun(entry_with_path):continue(如果函数有一个条目失败,它将被跳过),但代码越复杂,执行时间就越长Nota Bene!由于使用了递归,我必须提到我在我的笔记本电脑(Win 10 pc064)上做了一些测试,与这个问题完全无关,当递归级别达到(990..1000)范围内的某个值时(recursionlimit-1000(默认)),我得到了StackOverflow:)。如果目录树超过了这个限制(我不是FS专家,所以我不知道这是否可能),这可能是一个问题。我还必须提到,我没有尝试增加递归限制,但理论上,如果目录深度大于最高可能的递归限制(在该机器上),则始终存在失败的可能性。检查[SO]:_csv.Error:field大于字段限制(131072)(@CristiFati的答案)以了解有关该主题的更多详细信息代码示例仅用于演示目的。这意味着我没有考虑错误处理(我不认为有任何try/except/else/finally块),所以代码不健壮(原因是:尽量保持简单和简短)。对于生产,还应添加错误处理

其他方法:

1.仅将Python用作包装器

一切都是使用另一种技术完成的该技术是从Python调用的我所知道的最著名的风格是我所称的SysAdmin方法:使用Python(或任何编程语言)执行Shell命令(并解析其输出)有些人认为这是一个很好的方法我认为它更像是一个蹩脚的变通方法(gainarie),因为操作本身是从Shell(在本例中为Cmd)执行的,因此与Python无关过滤(grep/findstr)或输出格式化可以在两方面进行,但我不会坚持这样做。此外,我故意使用os.system而不是[Python.Docs]:subprocess-subprocess管理例程(run,check_output,…)

[提示]>“e:\Work\Dev\VEnvs\py_pc064_03.05.04_test0\Scripts\python.exe”-c“导入os;os.system(\”dir/b root_dir“)”目录0目录1目录2目录3文件0文件1


[cfati@cfati-5510-0:/mnt/e/Work/Dev/StackOverflow/q003207219]>python3.5-c“import os;os.system(\”ls root_dir\“)”目录0目录1目录2目录3文件0文件1

一般来说,应该避免这种方法,因为如果某些命令输出格式在操作系统版本/风格之间略有不同,那么解析代码也应该进行调整,更不用说地区之间的差异了。


Python 3.4+的另一个非常可读的变体是使用pathlib.Path.glob:

from pathlib import Path
folder = '/foo'
[f for f in Path(folder).glob('*') if f.is_file()]

更具体一些很简单,例如,只在所有子目录中查找非符号链接的Python源文件:

[f for f in Path(folder).glob('**/*.py') if not f.is_symlink()]

import os
import os.path


def get_files(target_dir):
    item_list = os.listdir(target_dir)

    file_list = list()
    for item in item_list:
        item_dir = os.path.join(target_dir,item)
        if os.path.isdir(item_dir):
            file_list += get_files(item_dir)
        else:
            file_list.append(item_dir)
    return file_list

这里我使用递归结构。


对于Python 2:

pip install rglob

那就做吧

import rglob
file_list = rglob.rglob("/home/base/dir/", "*")
print file_list

为了获得更好的结果,您可以使用os模块的listdir()方法和生成器(生成器是一个强大的迭代器,可以保持其状态,记得吗?)。以下代码适用于两个版本:Python 2和Python 3。

这里有一个代码:

import os

def files(path):  
    for file in os.listdir(path):
        if os.path.isfile(os.path.join(path, file)):
            yield file

for file in files("."):  
    print (file)

listdir()方法返回给定目录的条目列表。如果给定的条目是文件,则os.path.isfile()方法返回True。yield运算符退出func,但保持其当前状态,并且只返回作为文件检测到的条目的名称。以上所有内容都允许我们对生成器函数进行循环。


一位聪明的老师曾经告诉我:

当有几种既定的方法来做某事时,没有一种方法对所有情况都有好处。

因此,我将为问题的一个子集添加一个解决方案:通常,我们只想检查文件是否匹配开始字符串和结束字符串,而不需要进入子目录。因此,我们需要一个返回文件名列表的函数,例如:

filenames = dir_filter('foo/baz', radical='radical', extension='.txt')

如果您想首先声明两个函数,可以这样做:

def file_filter(filename, radical='', extension=''):
    "Check if a filename matches a radical and extension"
    if not filename:
        return False
    filename = filename.strip()
    return(filename.startswith(radical) and filename.endswith(extension))

def dir_filter(dirname='', radical='', extension=''):
    "Filter filenames in directory according to radical and extension"
    if not dirname:
        dirname = '.'
    return [filename for filename in os.listdir(dirname)
                if file_filter(filename, radical, extension)]

这个解决方案可以很容易地用正则表达式来概括(如果您不希望模式总是停留在文件名的开头或结尾,您可能需要添加一个模式参数)。