如何获取一个目录中的文件,包括所有子目录

77

我正试图获取目录中所有日志文件(.log),包括所有子目录。


1
这个问题已经被问过了:https://dev59.com/93RA5IYBdhLWcg3wwwzD,还有一些其他的(在搜索框中搜索“Python walk”)。 - Eli Bendersky
7个回答

131
import os
import os.path

for dirpath, dirnames, filenames in os.walk("."):
    for filename in [f for f in filenames if f.endswith(".log")]:
        print os.path.join(dirpath, filename)

2
如果你想在不同于“.”的目录中进行搜索,你可以将该目录作为sys.argv[1]传递,并调用os.walk(sys.argv[1])。 - lutz
2
额外的改进:使用生成器而不是列表推导式:for filename in (f for f ...) - lutz
3
如果您想要排除某个特定目录,例如 old_logs,您可以从 dirnames 中将其删除,这样它就不会被搜索到:if "old_logs" in dirnames: dirnames.remove("old_logs") - CGFoX
有没有更快的方法,比如使用multiprocessing.Pool()之类的东西? - Hzzkygcs
1
自从Python 3之后,print成为了一个函数,必须像这样调用:print(os.path.join(dirpath, filename)) - volkit

23

你也可以使用glob模块和os.walk一起使用。

import os
from glob import glob

files = []
start_dir = os.getcwd()
pattern   = "*.log"

for dir,_,_ in os.walk(start_dir):
    files.extend(glob(os.path.join(dir,pattern))) 

在for循环中,下划线的作用是什么?'_' - nu everest
2
@nueverest os.walk 在每次迭代时返回一个3元组 (dirpath, dirnames, filenames),我们只对 dirpath 感兴趣(在上面被赋值为 dir);下划线仅用作其他两个我们不感兴趣的值的占位符(即将 dirnamesfilenames 分别赋值给变量 _,我们将永远不会使用它们)。 - tavnab
为什么要运行glob并进行额外的I/O操作,当你已经有了filenames列表,可以使用fnmatch.filter进行过滤呢? - Cristian Ciupitu
1
这重新定义了 dir 函数,请使用 for directory,_,_ ... 替代。 - Chris Collett

8

5

一个仅使用列表推导式(嵌套)的单行解决方案:

import os

path_list = [os.path.join(dirpath,filename) for dirpath, _, filenames in os.walk('.') for filename in filenames if filename.endswith('.log')]

1
这个“一行代码”太长了。如果你超过了79个字符(参见PEP 8),它会降低可读性,应该将其拆分成多行或制作成函数(首选)。 - Chris Collett
没错,我发布这个主要是为了简单性和列表推导。将其拆分成多行确实很好。 - Frederik Baetens

2
我有一个解决方案:
import os
for logfile in os.popen('find . -type f -name *.log').read().split('\n')[0:-1]:
      print logfile

或者

import subprocess
(out, err) = subprocess.Popen(["find", ".", "-type", "f", "-name", "*.log"], stdout=subprocess.PIPE).communicate()
for logfile in out.split('\n')[0:-1]:
  print logfile

这两个命令都利用了 find . -type f -name *.log 的优势。
第一个更简单,但添加 -name *.log 后无法保证空格安全,但对于简单的 find ../testdata -type f 可以正常工作(在我的 OS X 环境中)。
第二个使用 subprocess 更复杂,但这是空格安全的(同样在我的 OS X 环境中)。
这是受 Chris Bunch 的启发,在答案中 https://dev59.com/4HA75IYBdhLWcg3wDUYo#3503909

1
使用标准库的 pathlib
from pathlib import Path

working_dir = Path()
for path in working_dir.glob("**/*.log"):
    print(path)
    # OR if you need absolute paths
    print(path.absolute())
    # OR if you need only filenames without extension for further parsing
    print(path.stem)

-1

如果你想列出当前目录,可以使用类似以下的命令:

import os

for e in os.walk(os.getcwd()):
    print e

只需要改变

os.getcwd()

到其他路径去获取结果。


2
这个回答并没有解答提问者的问题,而且对于大多数寻求相同答案的人来说也不相关。 - Andrew

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