提问



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

最佳参考


os.listdir()将为您提供目录中的所有内容 - 文件和目录。[173]


如果您想要只文件,可以使用os.path过滤掉它:[174]


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


或者您可以使用os.walk(),它会为它访问的每个目录生成两个列表 - 为您分割成文件和目录。如果你只想要顶级目录,你可以在它第一次产生[175]时中断


from os import walk

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


最后,如该示例所示,将一个列表添加到另一个列表,您可以使用.extend()[176]


>>> q = [1, 2, 3]
>>> w = [4, 5, 6]
>>> q = q + w
>>> q
[1, 2, 3, 4, 5, 6]


就个人而言,我更喜欢.extend()

其它参考1


我更喜欢使用glob模块,因为它模式匹配和扩展。[177]


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


它将返回包含查询文件的列表:


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

其它参考2


import os
os.listdir("somedirectory")


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

其它参考3


获取Python 2和3

的文件列表




我还在这里做了一个简短的视频: Python:如何获取文件列表目录 [178]





os.listdir()


或..... hot获取当前目录(Python 3)中的所有文件(和目录)


在Python 3中将文件放在当前目录中的最简单方法是这样。它非常简单;使用os模块和listdir()函数,你将在该目录中找到该文件(以及目录中的最终文件夹,但你不会在子目录中有该文件,为此你可以使用步行 - 我稍后会谈到它)。


>>> import os
>>> arr = os.listdir()
>>> arr
['$RECYCLE.BIN', 'work.txt', '3ebooks.txt', 'documents']





使用glob


我发现glob更容易选择相同类型的文件或共同的东西。请看以下示例:


import glob

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


使用列表理解


import glob

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


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



正如您所注意到的,您在上面的代码中没有文件的完整路径。如果您需要具有绝对路径,您可以使用os.path模块的另一个函数_getfullpathname,放置你从os.listdir()得到的文件作为一个参数。还有其他方法可以得到完整的路径,我们稍后会检查(我替换了,如mexmex所建议,_getfullpathname abspath)。


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





使用walk

获取所有子目录中文件类型的完整路径名

我发现这对于在许多目录中查找内容非常有用,它帮助我找到了一个我不记得名字的文件:


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 ".docx" in file:
            print(os.path.join(r, file))


os.listdir():获取当前目录中的文件(Python 2)


在Python 2中,如果您想要当前目录中的文件列表,则必须将参数设置为。。或os.listdir方法中的os.getcwd()。


>>> import os
>>> arr = os.listdir('.')
>>> arr
['$RECYCLE.BIN', 'work.txt', '3ebooks.txt', 'documents']


进入目录树



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

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


获取文件:os.listdir()在特定目录(Python 2和3)



>>> import os
>>> arr = os.listdir('F:\\python')
>>> arr
['$RECYCLE.BIN', 'work.txt', '3ebooks.txt', 'documents']


使用os.listdir()

获取特定子目录的文件

import os

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


os.walk() - 当前目录



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


glob模块 - 所有文件



import glob
print(glob.glob("*"))

out:['content', 'start.py']


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)

>output

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


next(os.walk(F:\\) - 获取完整路径 - 列表理解



>>> [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]

>>>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")]
>>> print(arr_txt)
['work.txt', '3ebooks.txt']


glob - 只获取txt文件



>>> import glob
>>> x = glob.glob("*.txt")
>>> x
['ale.txt', 'alunni2015.txt', 'assenze.text.txt', 'text2.txt', 'untitled.txt']


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



如果我需要文件的绝对路径:


>>> from path import path
>>> from glob import glob
>>> x = [path(f).abspath() for f in glob("F:\*.txt")]
>>> for f in x:
...  print(f)
...
F:\acquistionline.txt
F:\acquisti_2018.txt
F:\bootstrap_jquery_ecc.txt


glob的其他用途



如果我想要目录中的所有文件:


>>> x = glob.glob("*")


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



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

> output

['a simple game.py', 'data.txt', 'decorator.py']


使用(Python 3.4)

中的pathlib

import pathlib

>>> flist = []
>>> for p in pathlib.Path('.').iterdir():
...  if p.is_file():
...   print(p)
...   flist.append(p)
...
error.PNG
exemaker.bat
guiprova.mp3
setup.py
speak_gui2.py
thumb.PNG


如果你想使用列表理解


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


使用os.walk获取所有和唯一的文件



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

>>> y
['append_to_list.py', 'data.txt', 'data1.txt', 'data2.txt', 'data_180617', 'os_walk.py', 'READ2.py', 'read_data.py', 'somma_defaltdic.py', 'substitute_words.py', 'sum_data.py', 'data.txt', 'data1.txt', 'data_180617']


仅获取带有next的文件并进入目录



>>> import os
>>> x = next(os.walk('F://python'))[2]
>>> x
['calculator.bat','calculator.py']


仅获取带有next的目录并进入目录



>>> 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)
...
.vscode
pyexcel
pyschool.py
subtitles
_metaprogramming
.ipynb_checkpoints


来自Python 3.5 的

os.scandir()

>>> import os
>>> x = [f.name for f in os.scandir() if f.is_file()]
>>> x
['calculator.bat','calculator.py']

# 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)
...
ebookmaker.py
error.PNG
exemaker.bat
guiprova.mp3
setup.py
speakgui4.py
speak_gui2.py
speak_gui3.py
thumb.PNG
>>>





实施例。 1:子目录中有多少个文件?



在此示例中,我们查找包含在所有目录及其子目录中的文件数。


import os

def count(dir, counter=0):
    "returns number of files in dir and subdirs"
    for pack in os.walk(dir):
        for f in pack[2]:
            counter += 1
    return dir + " : " + str(counter) + "files"

print(count("F:\\python"))

> output

>'F:\\\python' : 12057 files'


例2:如何将目录中的所有文件复制到另一个目录?



一个脚本,用于在计算机中查找所有类型的文件(默认值:pptx)并将其复制到新文件夹中。


import os
import shutil
from path import path

destination = "F:\\file_copied"
# os.makedirs(destination)

def copyfile(dir, filetype='pptx', counter=0):
    "Searches for pptx (or other - pptx is the default) files and copies them"
    for pack in os.walk(dir):
        for f in pack[2]:
            if f.endswith(filetype):
                fullpath = pack[0] + "\\" + f
                print(fullpath)
                shutil.copy(fullpath, destination)
                counter += 1
    if counter > 0:
        print("------------------------")
        print("\t==> Found in: `" + dir + "` : " + str(counter) + " files\n")

for dir in os.listdir():
    "searches for folders that starts with `_`"
    if dir[0] == '_':
        # copyfile(dir, filetype='pdf')
        copyfile(dir, filetype='txt')


> Output

_compiti18\Compito Contabilità 1\conti.txt
_compiti18\Compito Contabilità 1\modula4.txt
_compiti18\Compito Contabilità 1\moduloa4.txt
------------------------
==> Found in: `_compiti18` : 3 files


实施例。 3:如何获取txt文件中的所有文件



如果您要创建包含所有文件名的txt文件:


import os
mylist = ""
with open("filelist.txt", "w", encoding="utf-8") as file:
    for eachfile in os.listdir():
        mylist += eachfile + "\n"
    file.write(mylist)

其它参考4


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


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


或绝对路径名:


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

其它参考5


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


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的子文件夹中。您现在可以执行以下操作:

  • print full_file_paths将打印清单:



    • ['/Users/johnny/Desktop/TEST/file1.txt', '/Users/johnny/Desktop/TEST/file2.txt', '/Users/johnny/Desktop/TEST/SUBFOLDER/file3.dat']




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


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


/Users/johnny/Desktop/TEST/SUBFOLDER/file3.dat

其它参考6


从版本3.4开始,内置迭代器,这比os.listdir()更有效:[179]


pathlib:版本3.4中的新内容。 [180]


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


根据PEP 428,pathlib库的目的是提供一个简单的类层次结构来处理文件系统路径以及用户对它们执行的常见操作。[181] [182]


os.scandir(): 3.5版中的新功能。 [183]​​]]


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


请注意,os.walk()使用os.scandir()代替版本3.5中的os.listdir(),并且根据PEP 471,其速度提高了2-20倍。[184] [185] [[[186] [187]


我还建议您阅读下面的ShadowRanger评论。

其它参考7


我真的很喜欢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库模块中可以找到的一些函数的强大功能。

其它参考8


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 

其它参考9


您应该使用os模块列出目录内容。os.listdir(".")返回目录的所有内容。我们迭代结果并附加到列表中。


import os

content_list = []

for content in os.listdir("."): # "." means current directory
    content_list.append(content)

print content_list

其它参考10


import os
lst=os.listdir(path)


os.listdir返回一个列表,其中包含path给出的目录中的条目名称。

其它参考11


第一部分



初步说明




  • 虽然问题文本中的 file 和目录术语有明显的区别,但有些人可能认为目录实际上是特殊文件

  • 声明:目录的所有文件可以用两种方式解释:


    1. 所有直接(或1级)后代

    2. 整个目录树中的所有后代(包括子目录中的后代)


  • 当问到这个问题时,我想 Python 2 ,是 LTS 版本,但是代码示例将由< em> Python 3 ( .5 )(我会尽可能地将它们视为 Python 2 ;同样,任何代码属于我要发布的 Python ,来自 v3.5.4 - 除非另有说明)。这会产生与问题中另一个关键字相关的后果:将它们添加到列表 中:



    • 在前 Python 2.2 版本中,序列(iterables)主要由列表(元组,集合......)表示

    • 在 Python 2.2 中,引入了 generator ([[Python]]:Generators)的概念 - 由[[Python]]提供:yield语句)。随着时间的推移,生成器对应物开始出现在返回/使用列表
    • 的函数中
    • 在 Python 3 中,generator是默认行为

    • 现在,我不知道返回列表是否仍然是强制性的(或者生成器也可以这样做),但是将生成器传递给list构造函数,将会创建一个列表(以及以下示例说明[[Python]]上的差异:地图(功能,可迭代,... )




    Python 2.7.10 (default, Mar  8 2016, 15:02:46) [MSC v.1600 64 bit (AMD64)] on win32
    Type "help", "copyright", "credits" or "license" for more information.
    >>> m = map(lambda x: x, [1, 2, 3])  # Just a dummy lambda function
    >>> m, type(m)
    ([1, 2, 3], <type 'list'>)
    >>> len(m)
    3
    



    结果,[189] [190] [191]



    Python 3.5.4 (v3.5.4:3f56838, Aug  8 2017, 02:17:05) [MSC v.1900 64 bit (AMD64)] on win32
    Type "help", "copyright", "credits" or "license" for more information.
    >>> m = map(lambda x: x, [1, 2, 3])
    >>> m, type(m)
    (<map object at 0x000001B4257342B0>, <class 'map'>)
    >>> len(m)
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    TypeError: object of type 'map' has no len()
    >>> lm0 = list(m)  # Construct a list out of the generator
    >>> lm0, type(lm0)
    ([1, 2, 3], <class 'list'>)
    >>>
    >>> lm1 = list(m)  # Construct a list out of the same generator
    >>> lm1, type(lm1)  # Empty list this time - generator already consumed
    ([], <class 'list'>)
    


  • 示例将基于名为 root_dir 的目录,具有以下结构(此示例适用于 Win ,但我已复制 Ux的文件夹树( Lnx )):



    E:\Work\Dev\StackOverflow\q003207219>tree /f "root_dir"
    Folder PATH listing for volume Work
    Volume serial number is 00000029 3655:6FED
    E:\WORK\DEV\STACKOVERFLOW\Q003207219\ROOT_DIR
    │   file0
    │   file1
    │
    ├───dir0
    │   ├───dir00
    │   │   │   file000
    │   │   │
    │   │   └───dir000
    │   │           file0000
    │   │
    │   ├───dir01
    │   │       file010
    │   │       file011
    │   │
    │   └───dir02
    │       └───dir020
    │           └───dir0200
    ├───dir1
    │       file10
    │       file11
    │       file12
    │
    ├───dir2
    │   │   file20
    │   │
    │   └───dir20
    │           file200
    │
    └───dir3
    




点击


解决方案



程序化方法:




  1. [[Python]]:os。 listdir ( path =。)[192]



      返回一个列表,其中包含path给出的目录中的条目名称。该列表按任意顺序排列,不包括特殊条目'.''..' ......



    点击



    >>> import os
    >>> root_dir = "root_dir"  # Path relative to current dir (os.getcwd())
    >>>
    >>> os.listdir(root_dir)  # List all the items in root_dir
    ['dir0', 'dir1', 'dir2', 'dir3', 'file0', 'file1']
    >>>
    >>> [item for item in os.listdir(root_dir) if os.path.isfile(os.path.join(root_dir, item))]  # Filter the items and only keep files (strip out directories)
    ['file0', 'file1']
    



    这是一个更详细的例子( code_os_listdir.py ):


    import os
    from pprint import pformat
    
    
    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():
        root_dir = "root_dir"
        ret0 = get_dir_content(root_dir, include_folders=True, recursive=True, prepend_folder_name=True)
        lret0 = list(ret0)
        print(ret0, len(lret0), pformat(lret0))
        ret1 = get_dir_content_old(root_dir, include_folders=False, recursive=True, prepend_folder_name=False)
        print(len(ret1), pformat(ret1))
    
    
    if __name__ == "__main__":
        main()
    


    备注:



    • 有两种实现方式:


      • 使用生成器的人(当然在这个例子中它似乎没用,因为我立即将结果转换为列表)

      • 经典的(功能名称以 _old 结尾)


    • 使用递归(进入子目录)

    • 对于每个实现,有两个功能:


      • 一个以下划线( _ )开头:私人(不应该直接调用) - 完成所有工作

      • public one(前一个包装器):它只是从返回的条目中剥离初始路径(如果需要)。这是一个丑陋的实现,但这是我此时唯一的想法


    • 在性能方面,生成器通常要快一点(考虑创建和迭代次),但我没有在递归函数中测试它们,我也在内部生成器内部迭代函数 - 不知道性能如何

    • 使用参数来获得不同的结果



    点击


    输出:



    (py35x64_test) E:\Work\Dev\StackOverflow\q003207219>"e:\Work\Dev\VEnvs\py35x64_test\Scripts\python.exe" "code_os_listdir.py"
    <generator object get_dir_content at 0x000001BDDBB3DF10> 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',
     'file0',
     'file1']
    




点击



  1. [[Python]]:os。 scandir ( path =。)( !!! Python 3.5 + !!! 虽然我认为对于早期版本它是一个单独的模块(也移植到 Python 2 ))[193]]]



      返回与 path 给出的目录中的条目对应的os.DirEntry对象的迭代器。条目以任意顺序产生,并且不包括特殊条目'.''..'[194]

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



    点击



    >>> import os
    >>> root_dir = os.path.join(".", "root_dir")  # Explicitly prepending current directory
    >>> root_dir
    '.\\root_dir'
    >>>
    >>> scandir_iterator = os.scandir(root_dir)
    >>> scandir_iterator
    <nt.ScandirIterator object at 0x00000268CF4BC140>
    >>> [item.path for item in scandir_iterator]
    ['.\\root_dir\\dir0', '.\\root_dir\\dir1', '.\\root_dir\\dir2', '.\\root_dir\\dir3', '.\\root_dir\\file0', '.\\root_dir\\file1']
    >>>
    >>> [item.path for item in scandir_iterator]  # Will yield an empty list as it was consumed by previous iteration (automatically performed by the list comprehension)
    []
    >>>
    >>> scandir_iterator = os.scandir(root_dir)  # Reinitialize the generator
    >>> for item in scandir_iterator :
    ...     if os.path.isfile(item.path):
    ...             print(item.name)
    ...
    file0
    file1
    



    备注:



    • os.listdir
    • 类似
    • 但它也更灵活(并提供更多功能),更多 Python ic(在某些情况下,更快)




点击



  1. [[Python]]:os。行走( top,topdown=True,onerror=None,followlinks=False )[202]



      通过从上到下或从下到上遍历树来生成目录树中的文件名。对于以 top 目录(包括 top 本身)为目标的树中的每个目录,它会产生一个3元组(dirpathdirnames,[[filenames)。



    点击



    >>> import os
    >>> root_dir = os.path.join(os.getcwd(), "root_dir")  # Specify the full path
    >>> root_dir
    'E:\\Work\\Dev\\StackOverflow\\q003207219\\root_dir'
    >>>
    >>> walk_generator = os.walk(root_dir)
    >>> root_dir_entry = next(walk_generator)  # First entry corresponds to the root dir (that was passed as an argument)
    >>> root_dir_entry
    ('E:\\Work\\Dev\\StackOverflow\\q003207219\\root_dir', ['dir0', 'dir1', 'dir2', 'dir3'], ['file0', 'file1'])
    >>>
    >>> root_dir_entry[1] + root_dir_entry[2]  # Display the dirs and the files (that are direct descendants) in a single list
    ['dir0', 'dir1', 'dir2', 'dir3', 'file0', 'file1']
    >>>
    >>> [os.path.join(root_dir_entry[0], item) for item in root_dir_entry[1] + root_dir_entry[2]]  # Display all the entries in the previous list by their full path
    ['E:\\Work\\Dev\\StackOverflow\\q003207219\\root_dir\\dir0', 'E:\\Work\\Dev\\StackOverflow\\q003207219\\root_dir\\dir1', 'E:\\Work\\Dev\\StackOverflow\\q003207219\\root_dir\\dir2', 'E:\\Work\\Dev\\StackOverflow\\q003207219\\root_dir\\dir3', 'E:\\Work\\Dev\\StackOverflow\\q003207219\\root_dir\\file0', 'E:\\Work\\Dev\\StackOverflow\\q003207219\\root_dir\\file1']
    >>>
    >>> for entry in walk_generator:  # Display the rest of the elements (corresponding to every subdir)
    ...     print(entry)
    ...
    ('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', 'file12'])
    ('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.listdir(os.scandir可用的地方)

    • 通过在子文件夹中重复出现来解决繁重问题




点击



  1. [[Python]]:glob。 glob ( pathname,*,recursive=False )([[Python]]:glob。 iglob (< em> pathname,*,recursive=False ))[203] [204]



      返回与 pathname 匹配的可能为空的路径名列表,该列表必须是包含路径规范的字符串。 pathname 可以是绝对的(如/usr/src/Python-1.5/Makefile)或相对的(如../../Tools/*/*.gif),也可以包含shell样式的通配符。结果中包含损坏的符号链接(如在shell中)。


    在版本3.5中更改 :使用[[支持递归globs]] 132]]。



    点击



    >>> import glob, os
    >>> wildcard_pattern = "*"
    >>> root_dir = os.path.join("root_dir", wildcard_pattern)  # Match every file/dir name
    >>> root_dir
    'root_dir\\*'
    >>>
    >>> glob_list = glob.glob(root_dir)
    >>> glob_list
    ['root_dir\\dir0', 'root_dir\\dir1', 'root_dir\\dir2', 'root_dir\\dir3', 'root_dir\\file0', 'root_dir\\file1']
    >>>
    >>> [item.replace("root_dir" + os.path.sep, "") for item in glob_list]  # Strip the dir name and the path separator from begining
    ['dir0', 'dir1', 'dir2', 'dir3', 'file0', 'file1']
    >>>
    >>> for entry in glob.iglob(root_dir + "*", recursive=True):
    ...     print(entry)
    ...
    root_dir\
    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
    



    备注:



    • 使用os.listdir

    • 对于大型树木(尤其是recursive开启时),iglob是首选

    • 允许基于名称的高级过滤(由于通配符)




点击



  1. [[Python]]:类pathlib。路径( * pathsegments )( !!! Python 3 + !!! 不知道是否向后移植了[205]



    >>> import pathlib
    >>> root_dir = "root_dir"
    >>> root_dir_instance = pathlib.Path(root_dir)
    >>> root_dir_instance
    WindowsPath('root_dir')
    >>> root_dir_instance.name
    'root_dir'
    >>> root_dir_instance.is_dir()
    True
    >>>
    >>> [item.name for item in root_dir_instance.glob("*")]  # Wildcard searching for all direct descendants
    ['dir0', 'dir1', 'dir2', 'dir3', 'file0', 'file1']
    >>>
    >>> [os.path.join(item.parent.name, item.name) for item in root_dir_instance.glob("*") if not item.is_dir()]  # Display paths (including parent) for files only
    ['root_dir\\file0', 'root_dir\\file1']
    



    备注:



    • 这是实现目标的一种方式

    • 处理路径的 OOP 风格

    • 提供许多功能




点击



  1. [[Python]]:dircache.listdir(path)( !!!
    已删除 Python 3 !!! )[206]



    • 但是,根据 $ {PYTHON_SRC_DIR}/Lib/dircache.py :〜#20 +(来自 v2.7.14 ),它只是os.listdir
    • 上的(薄)包装


    点击


    def listdir(path):
        """List directory contents, using cache."""
        try:
            cached_mtime, list = cache[path]
            del cache[path]
        except KeyError:
            cached_mtime, list = -1, []
        mtime = os.stat(path).st_mtime
        if mtime != cached_mtime:
            list = os.listdir(path)
            list.sort()
        cache[path] = mtime, list
        return list
    



点击



  1. [[man]]:OPENDIR(3)/[[man]]:READDIR(3)/[[man]]:CLOSEDIR(3)来自[[Python]]:ctypes - Python的外部函数库( !!! Ux 具体 !!! )[207] [208] [209] [210]



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



    code_ctypes.py :


    #!/usr/bin/env python3
    
    import sys
    from ctypes import Structure, \
        c_ulonglong, c_longlong, c_ushort, c_ubyte, c_char, c_int, \
        CDLL, POINTER, \
        create_string_buffer, get_errno, set_errno, cast, sizeof
    
    
    DT_DIR = 4
    DT_REG = 8
    
    char256 = c_char * 256
    
    class LinuxDirent64(Structure):
        _fields_ = [
            ("d_ino", c_ulonglong),
            ("d_off", c_longlong),
            ("d_reclen", c_ushort),
            ("d_type", c_ubyte),
            ("d_name", char256),
        ]
    
    LinuxDirent64Ptr = POINTER(LinuxDirent64)
    
    libc_dll = CDLL(None)
    opendir = libc_dll.opendir
    readdir = libc_dll.readdir
    closedir = libc_dll.closedir
    libc_dll.__errno_location.restype = POINTER(c_int)
    errno_loc_func = libc_dll.__errno_location
    
    
    def _get_errno():
        return "errno: {:d}({:d})".format(get_errno(), errno_loc_func().contents.value)
    
    
    def get_dir_content(path):
        ret = [path, list(), list()]
        dir_stream = opendir(create_string_buffer(path.encode()))
        if (dir_stream == 0):
            print("opendir returned NULL ({:s})".format(_get_errno()))
            return ret
        set_errno(0)
        dirent_addr = readdir(dir_stream)
        while dirent_addr:
            dirent_ptr = cast(dirent_addr, LinuxDirent64Ptr)
            dirent = dirent_ptr.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)
            dirent_addr = readdir(dir_stream)
        if get_errno() or errno_loc_func().contents.value:
            print("readdir returned NULL ({:s})".format(_get_errno()))
        closedir(dir_stream)
        return ret
    
    
    def main():
        print("{:s} on {:s}\n".format(sys.version, sys.platform))
        root_dir = "root_dir"
        entries = get_dir_content(root_dir)
        print(entries)
    
    
    if __name__ == "__main__":
        main()
    


    备注:



    • 它从 libc 加载三个函数(在当前进程中加载​​)并调用它们(有关更多详细信息,请检查[[Stack  Overflow]]:如何使用Python检查文件是否存在?( @CristiFati的回答) - 项目 #4。 的最后一个注释。这将使这种方法非常接近 Python / C 边缘

    • LinuxDirent64是来自 dirent.h 的struct dirent64的 ctypes 表示(我的机器DT_*常量也是如此) : Ubtu 16 x64 ( 4.10.0-40-generic 和 libc6-dev:amd64 )。在其他版本/版本上,结构定义可能不同,如果是,则应更新 ctypes 别名,否则将产生未定义行为

    • errno_loc_func(以及与之相关的所有内容)是因为funcs在出现错误时设置errno,我需要检查它的值。显然,get_errno不起作用(名称无效,opendir返回NULL,但get_errno仍然返回0),或者我还没弄清楚

    • os.walk的格式返回数据。我没有理由让它递归,但从现有代码开始,这将是一项相当简单的任务

    • Win 上的一切都是可行的,数据(库,函数,结构,常量......)不同



    结果,


    输出:



    cfati@testserver:~/work/stackoverflow/q003207219$ ./code_ctypes.py
    3.5.2 (default, Nov 23 2017, 16:37:01)
    [GCC 5.4.0 20160609] on linux
    
    ['root_dir', ['dir3', 'dir2', 'dir0', 'dir1'], ['file0', 'file1']]
    




点击



  1. [[ActiveState]]:win32file.FindFilesW( !!! Win 具体 !!! )[213]



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



    点击



    >>> import os, win32file, win32con
    >>> root_dir = "root_dir"
    >>> wildcard = "*"
    >>> root_dir_wildcard = os.path.join(root_dir, wildcard)
    >>> entry_list = win32file.FindFilesW(root_dir_wildcard)
    >>> len(entry_list)  # Don't display the whole content as it's too long
    8
    >>> [entry[-2] for entry in entry_list]  # Only display the entry names
    ['.', '..', 'dir0', 'dir1', 'dir2', 'dir3', 'file0', 'file1']
    >>>
    >>> [entry[-2] for entry in entry_list if entry[0] & win32con.FILE_ATTRIBUTE_DIRECTORY and entry[-2] not in (".", "..")]  # Filter entries and only display dir names (except self and parent)
    ['dir0', 'dir1', 'dir2', 'dir3']
    >>>
    >>> [os.path.join(root_dir, entry[-2]) for entry in entry_list if entry[0] & (win32con.FILE_ATTRIBUTE_NORMAL | win32con.FILE_ATTRIBUTE_ARCHIVE)]  # Only display file "full" names
    ['root_dir\\file0', 'root_dir\\file1']
    



    备注:



    • win32file.FindFilesW是[[GitHub]]的一部分:Python for Windows(pywin32)Extensions,它是 Python 包装器,通过 WINAPI s

    • 文档链接来自https://www.activestate.com,因为我没有找到任何 pywin32 官方文档




结果,[214] [215]



  1. 安装一些(其他)第三方软件包


    • 最有可能的,将依赖于上述中的一个(或多个)(可能有轻微的自定义)




点击


备注(关于上述内容):



  • 代码是可移植的(除了针对特定区域的地方 - 已标记的)或交叉:


    • platform( Ux , Win ,)

    • Python 版本(2,3,)


  • 在上述变体中使用了多种路径样式(绝对,亲属),以说明所使用的工具在这个方向上是灵活的

  • os.listdiros.scandir使用opendir/readdir/closedir([[MSDN]]:FindFirstFile函数/[[MSDN]]:FindNextFile函数/[[MSDN]] :FindClose函数)(通过 $ {PYTHON_SRC_DIR}/Modules/posixmodule.c )

  • win32file.FindFilesW也使用那些( Win 特定)函数(通过 $ {PYWIN32_SRC_DIR}/win32/src/win32file.i )

  • get_dir_content(从点#1。)可以使用这些方法中的任何一种来实现(一些需要更多工作,一些需要更少)


    • 可以完成一些高级过滤(而不仅仅是文件 vs。 dir):例如include_folders参数可以被另一个参数替换(例如filter_func),它将是一个以路径作为参数的函数:filter_func=lambda x: True(这不会剥离任何东西)和里面get_dir_content类似于:if not filter_func(entry_with_path): continue(如果一个条目的函数失败,它将被跳过),但代码越复杂,执行的时间就越长


  • Nota bene!由于使用了递归,我必须提到我在笔记本电脑上做了一些测试( Win 10 x64 ),与此问题完全无关,以及何时递归级别在(990 .. 1000)范围( recursionlimit - 1000(默认值))的某处达到了值,我得到了 StackOverflow : )。如果目录树超过了该限制(我不是 FS 专家,所以我不知道这是否可能),这可能是一个问题。

    我还必须提一下,我没有尝试增加 recursionlimit ,因为我没有该领域的经验(在不得不增加 OS 级别),但理论上如果dir深度大于最高可能 recursionlimit (在该机器上),则总会有失败的可能性

  • 代码示例为fo仅用于示范目的。这意味着我没有考虑错误处理(我认为没有try/except/else/finally块,所以代码不健壮(原因是:尽可能简单和简短)。对于生产,还应添加错误处理



第一部分结尾



结果,[216] [217] [218]


(转到第二部分。)

其它参考12


如果您正在寻找查找的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存储库。我希望有人发现它对这段代码有用。[220] [221]

其它参考13


Python 3.5引入了一种新的,更快的方法来遍历目录 - os.scandir()[222]


例:


for file in os.scandir('/usr/bin'):
    line = ''
    if file.is_file():
        line += 'f'
    elif file.is_dir():
        line += 'd'
    elif file.is_symlink():
        line += 'l'
    line += '\t'
    print("{}{}".format(line, file.name))

其它参考14


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


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

其它参考15


列出目录中的所有文件:


import os
from os import path

files = [x for x in os.listdir(directory_path) if path.isfile(directory_path+os.sep+x)]


在这里,您将获得目录中所有文件的列表。

其它参考16


# -** coding: utf-8 -*-
import os
import traceback

print '\n\n'

def start():
    address = "/home/ubuntu/Desktop"
    try:
        Folders = []
        Id = 1
        for item in os.listdir(address):
            endaddress = address + "/" + item
            Folders.append({'Id': Id, 'TopId': 0, 'Name': item, 'Address': endaddress })
            Id += 1         

            state = 0
            for item2 in os.listdir(endaddress):
                state = 1
            if state == 1: 
                Id = FolderToList(endaddress, Id, Id - 1, Folders)
        return Folders
    except:
        print "___________________________ ERROR ___________________________\n" + traceback.format_exc()

def FolderToList(address, Id, TopId, Folders):
    for item in os.listdir(address):
        endaddress = address + "/" + item
        Folders.append({'Id': Id, 'TopId': TopId, 'Name': item, 'Address': endaddress })
        Id += 1

        state = 0
        for item in os.listdir(endaddress):
            state = 1
        if state == 1: 
            Id = FolderToList(endaddress, Id, Id - 1, Folders)
    return Id

print start()

其它参考17


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

其它参考18


使用发电机


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)

其它参考19


如果您关心性能,请尝试scandir。对于Python 2.x,您可能需要手动安装它。例子:


# python 2.x
import scandir
import sys

de = scandir.scandir(sys.argv[1])
while 1:
    try:
        d = de.next()
        print d.path
    except StopIteration as _:
        break


当您需要扫描一个巨大的目录时,这可以节省大量的时间,而且您不需要缓冲一个巨大的列表,只需逐个获取。而且你也可以递归地做到:


def scan_path(path):
    de = scandir.scandir(path)
    while 1:
        try:
            e = de.next()
            if e.is_dir():
                scan_path(e.path)
            else:
                print e.path
        except StopIteration as _:
                break

其它参考20


如果要使用其他文件类型或获取完整目录,请使用此功能:


import os

def createList(foldername, fulldir = True, suffix=".jpg"):
    file_list_tmp = os.listdir(foldername)
    #print len(file_list_tmp)
    file_list = []
    if fulldir:
        for item in file_list_tmp:
            if item.endswith(suffix):
                file_list.append(os.path.join(foldername, item))
    else:
        for item in file_list_tmp:
            if item.endswith(suffix):
                file_list.append(item)
    return file_list

其它参考21


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


在这里,我使用递归结构。

其它参考22


使用os库。[223]


import os
for root, dirs,files in os.walk("your dir path", topdown=True):
    for name in files:
        print(os.path.join(root, name))

其它参考23


import os 
os.listdir(path)


这将返回path中所有文件和目录的列表。


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


这将只返回文件列表,而不是子目录。

其它参考24


以目录作为参数执行findfiles(),它将返回其中所有文件的列表。


import os
def findfiles(directory):
    objects = os.listdir(directory)  # find all objects in a dir

    files = []
    for i in objects:  # check if very object in the folder ...
        if os.path.isfile(os.path.join(directory, i)):  # ... is a file.
            files.append(i)  # if yes, append it.
    return files

其它参考25


参考@adamk的答案,这是我的os检测方法,以响应@Anti Earth 的斜线不一致性评论


import sys
import os
from pathlib import Path
from glob import glob
platformtype = sys.platform
if platformtype == 'win32':
    slash = "\\"
if platformtype == 'darwin':
    slash = "/"

# TODO: How can I list all files of a directory in Python and add them to a list?

# Step 1 - List all files of a directory

# Method 1: Find only pre-defined filetypes (.txt) and no subfiles, answer provided by @adamk
dir1 = "%sfoo%sbar%s*.txt" % (slash)
_files = glob(dir1)

# Method 2: Find all files and no subfiles
dir2 = "%sfoo%sbar%s" % (slash)
_files = (x for x in Path("dir2").iterdir() if x.is_file())

# Method 3: Find all files and all subfiles
dir3 = "%sfoo%sbar" % (slash)
_files = (x for x in Path('dir3').glob('**/*') if x.is_file())


# Step 2 - Add them to a list

files_list = []
for eachfiles in _files:
    files_basename = os.path.basename(eachfiles)
    files_list.append(files_basename)





print(files_list)
['file1.txt', 'file2.txt', .... ]


我假设您只想要列表中的基本名称。


请参阅此文章,以预先定义方法1的多种文件格式。

其它参考26


我将提供一个样本一个衬管,其中可以提供源路径和文件类型作为输入。该代码返回带有csv扩展名的文件名列表。如果需要返回所有文件,请使用。。这也将递归扫描子目录。


[y for x in os.walk(sourcePath) for y in glob(os.path.join(x[0], '*.csv'))]


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

其它参考27


真正简单的版本:


import os
[f for f in os.listdir(os.getcwd) if ...]

其它参考28


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()]

其它参考29


(另见第1部分。)


第二部分



解决方案(续)



其他方法:




  1. 仅将 Python 用作包装器



    • 一切都是使用其他技术完成的

    • 该技术是从 Python
    • 调用的
    • 我所知道的最着名的风格是我称之为系统管理员的方法:



      • 使用 Python (或任何编程语言)来执行 shell 命令(并解析其输出 - 通常这种方法应该避免,因为如果某些命令输出格式在 OS 版本/版本之间略有不同,则解析代码也应该进行调整;更不用说非 EN 区域设置了)

      • 有些人认为这是一个整洁的黑客

      • 我认为它更像是一种蹩脚的解决方法( gainarie ),因为操作本身是从 shell 执行的( cmd 在这种情况下),因此与 Python 没有任何关系。

      • 过滤(grep/findstr)或输出格式可以在双方进行,但我不会坚持它。而且,我故意使用os.system而不是subprocess.Popen




      (py35x64_test) E:\Work\Dev\StackOverflow\q003207219>"e:\Work\Dev\VEnvs\py35x64_test\Scripts\python.exe" -c "import os;os.system(\"dir /b root_dir\")"
      dir0
      dir1
      dir2
      dir3
      file0
      file1