获取目录中所有文件的绝对路径

102

如何在Python中获取目录中所有文件的绝对路径,而该目录可能有许多子文件夹?

我知道os.walk()可以递归地给出目录和文件的列表,但似乎无法得到我想要的结果。


你能否举个例子,说明你期望的输入和输出是什么? - cwallenpoole
12个回答

108

os.path.abspath 确保路径是绝对路径。使用以下辅助函数:

import os

def absoluteFilePaths(directory):
    for dirpath,_,filenames in os.walk(directory):
        for f in filenames:
            yield os.path.abspath(os.path.join(dirpath, f))

4
我认为在os.walk行中执行一次abspath比在循环内部执行N次更好。 - wim
1
这个可以工作,但只是“偶然”的。阅读os.path.join的合同,我找不到任何保证结果是绝对路径的地方,即使其中一个参数是绝对路径,尽管这是一个明智的假设。 - phihag
1
@phihag 这是可靠的。它不是“意外”,语言也不太正式,没有任何关于“合同”的概念在文档中。文档记录了如果组件是绝对路径,则所有先前的组件都被丢弃,并且连接继续从绝对路径组件开始。Python 无法在此处隐式转换为相对路径,而且要修改行为将是不可能的,因为这会导致巨大的向后不兼容性变化。如果仍然不信,请阅读 os.path.join 的源代码,它很短而简单。 - wim

37
如果传递给 os.walk 的参数是绝对路径,则迭代期间生成的根目录名称也将是绝对路径。因此,您只需将它们与文件名连接即可:
import os

for root, dirs, files in os.walk(os.path.abspath("../path/to/dir/")):
    for file in files:
        print(os.path.join(root, file))

好的,我明白你的意思了,只是我不想要文件,而是想要特定的子目录。我在下面发布了解决方案。 - Eamonn Kenny

35

您可以使用标准库 pathlib(或者如果您的 Python 版本小于 3.4,则使用 backport):

import pathlib
for filepath in pathlib.Path(directory).glob('**/*'):
    print(filepath.absolute())

4
很棒它使用了Python 3,但它也显示了目录。 - Newskooler
@Newskooler,可以再次使用Pathlib中的iterdir - spen.smith

10

尝试:

import os

for root, dirs, files in os.walk('.'):
    for file in files:
        p=os.path.join(root,file)
        print p
        print os.path.abspath(p)
        print

有没有不捕获隐藏文件的方法来完成这个任务? - Marcel Marino
@MarcelMarino if not file.startswith('.') 如果文件名不以'.'开头,则执行该操作。 - A.Wan

9
您可以使用os.path.abspath()将相对路径转换为绝对路径:
file_paths = []

for folder, subs, files in os.walk(rootdir):
  for filename in files:
    file_paths.append(os.path.abspath(os.path.join(folder, filename)))

1
这不是将 cwdfilename 连接起来吗?你想要连接的是 folder 吧! - wim
root_path="<你的根路径>" file_paths = [path for folder, subs, files in os.walk(root_path) for filename in files for path in os.path.abspath(os.path.join(folder, filename))] - undefined

8

从Python 3.5开始,惯用的解决方案是:

import os

def absolute_file_paths(directory):
    path = os.path.abspath(directory)
    return [entry.path for entry in os.scandir(path) if entry.is_file()]

这不仅读起来更加流畅,而且在许多情况下也更快。 有关更多详细信息(如忽略符号链接),请参阅原始的Python文档: https://docs.python.org/3/library/os.html#os.scandir


1
scandir() 不是递归的。 - crypdick
而且 os.walk 无论如何都会使用可用的 scandir。(参考) - wim

5

所有文件和文件夹:

x = [os.path.abspath(os.path.join(directory, p)) for p in os.listdir(directory)]

图片(.jpg | .png):

x = [os.path.abspath(os.path.join(directory, p)) for p in os.listdir(directory) if p.endswith(('jpg', 'png'))]

你怎么确保这个单行命令只是文件而不是目录? - Doons

3
from glob import glob


def absolute_file_paths(directory):
    return glob(join(directory, "**"))

6
虽然这段代码可能回答了问题,但您仍然可以考虑添加一些解释性句子,因为这能增加其他用户对您答案的价值。 - MBT
1
只有在您还从os模块导入join时,它才能正常工作,如下所示:from os.path import join。不会递归地处理文件夹。 - martin-martin

1

尝试:

from pathlib import Path
path = 'Desktop'
files = filter(lambda filepath: filepath.is_file(), Path(path).glob('*'))
for file in files:
   print(file.absolute())

你的导入语句直接导入了 Path,但是在代码中却调用了 pathlib.Path()。除非你修复这个问题,否则代码无法运行。不过,@Pygirl 的解决方案很好且干净。 - martin-martin
在这个例子中,没有必要将这些文件制作成list,filter返回一个生成器。 - MaLiN2223
1
@MaLiN2223: 是的,你说得没错。但我想存储文件列表,因为当生成器耗尽时,文件将不会被给予。无论如何,我已经更新了我的答案 :) - Pygirl

0

我想保留子目录的详细信息,但不要包含文件,只需要其中有一个 xml 文件的子目录。可以这样实现:

for rootDirectory, subDirectories, files in os.walk(eventDirectory):
  for subDirectory in subDirectories:
    absSubDir = os.path.join(rootDirectory, subDirectory)
    if len(glob.glob(os.path.join(absSubDir, "*.xml"))) == 1:
      print "Parsing information in " + absSubDir

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