如何在os.listdir中查找文件并跳过目录

52
我使用 os.listdir,它有效地工作,但是列表中也包含子目录,这不是我想要的:我只需要文件。
我需要使用哪个函数才能实现?
我还查看了 os.walk,它似乎是我想要的东西,但我不确定它是如何工作的。
7个回答

75

你需要过滤掉目录;os.listdir()列出给定路径中的所有名称。你可以使用os.path.isdir()来实现:

basepath = '/path/to/directory'
for fname in os.listdir(basepath):
    path = os.path.join(basepath, fname)
    if os.path.isdir(path):
        # skip directories
        continue

请注意,这只会在跟踪符号链接后过滤掉目录。 fname 不一定是一个普通文件,它也可能是指向文件的符号链接。如果您还需要过滤掉符号链接,则需要先使用not os.path.islink()

在现代 Python 版本(3.5 或更高版本),甚至更好的选择是使用os.scandir()函数; 这将产生DirEntry()实例。在常见情况下,这比先前加载所有信息来确定条目是否为目录快得多:

basepath = '/path/to/directory'
for entry in os.scandir(basepath):
    if entry.is_dir():
        # skip directories
        continue
    # use entry.path to get the full path of this entry, or use
    # entry.name for the base filename

如果只需要普通文件(而不是符号链接),则可以使用 entry.is_file(follow_symlinks=False)

os.walk() 在幕后执行相同的工作;除非需要递归遍历子目录,否则不需要在此处使用 os.walk()


微小的更改会抛出错误 "AttributeError:'posix.DirEntry'对象没有属性'isdir'" - is_dir 是正确的方法名称。 - mdmjsh

28

这是一个很好的一行代码,采用列表推导式的形式:

[f for f in os.listdir(your_directory) if os.path.isfile(os.path.join(your_directory, f))]

这将返回指定your_directory中的文件名列表。


6
替代方案:filter(os.path.isfile, os.listdir(你的目录)) - Valentin Lorentz
6
实际上这并不起作用,因为f只是文件名,而不是完整路径。你需要在那里使用 os.path.isfile(os.path.join(your_directory, f)) - Martijn Pieters
1
我更喜欢这个版本,并且我也想将其限制为一个扩展名,因此能够在结尾添加另一个条件:and f.endswith('.txt') - Nikhil VJ

8
import os
directoryOfChoice = "C:\\" # Replace with a directory of choice!!!
filter(os.path.isfile, os.listdir(directoryOfChoice))

P.S: os.getcwd() 返回当前目录。


7
for fname in os.listdir('.'):
    if os.path.isdir(fname):
       pass  # do your stuff here for directory
    else:
       pass  # do your stuff here for regular file

2

使用os.walk()的解决方案如下:

for r, d, f in os.walk('path/to/dir'):
    for files in f:
       # This will list all files given in a particular directory

1
如果你只是简单地复制/粘贴这段代码,不太明显的是它将循环遍历起始目录下所有子目录中的所有目录。 - tripleee

0
注意PEP 471 DirEntry对象属性为:is_dir(*, follow_symlinks=True)
所以...
from os import scandir
folder = '/home/myfolder/'
for entry in scandir(folder):
    if entry.is_dir():
        # do code or skip
        continue
    myfile = folder + entry.name
    #do something with myfile

    

0
尽管这是一篇较旧的文章,但为了完整起见,请让我添加在3.4中引入的pathlib库,它提供了一种面向对象的处理目录和文件的方式。要获取目录中的所有文件,您可以使用:
def get_list_of_files_in_dir(directory: str, file_types: str ='*') -> list:
    return [f for f in Path(directory).glob(file_types) if f.is_file()]

根据您的示例,您可以像这样使用它:

mypath = '/path/to/directory'
files = get_list_of_files_in_dir(mypath)

如果您只想获取特定文件扩展名的子集(例如“仅限csv文件”),可以使用以下代码:
files = get_list_of_files_in_dir(mypath, '*.csv')

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接