203

我需要遍历给定目录的子目录并搜索文件。如果我得到一个文件,我必须打开它并更改内容并用我自己的行替换它。

我试过这个:

import os

rootdir ='C:/Users/sid/Desktop/test'

for subdir, dirs, files in os.walk(rootdir):
    for file in files:
        f=open(file,'r')
        lines=f.readlines()
        f.close()
        f=open(file,'w')
        for line in lines:
            newline = "No you are not"
            f.write(newline)
        f.close()

但我收到一个错误。我究竟做错了什么?

4

3 回答 3

385

实际浏览目录的工作方式与您编写的代码相同。如果你用一个简单的语句替换内部循环的内容,print你可以看到每个文件都找到了:

import os
rootdir = 'C:/Users/sid/Desktop/test'

for subdir, dirs, files in os.walk(rootdir):
    for file in files:
        print os.path.join(subdir, file)

如果在运行上述程序时仍然出现错误,请提供错误消息。


针对 Python3 更新

import os
rootdir = 'C:/Users/sid/Desktop/test'

for subdir, dirs, files in os.walk(rootdir):
    for file in files:
        print(os.path.join(subdir, file))
于 2013-10-25T10:39:02.057 回答
27

返回子目录中所有文件的另一种方法是使用Python 3.4 中引入pathlib模块,它提供了一种面向对象的方法来处理文件系统路径(Pathlib 在 Python 2.7 上也可以通过PyPi 上的 pathlib2 模块获得):

from pathlib import Path

rootdir = Path('C:/Users/sid/Desktop/test')
# Return a list of regular files only, not directories
file_list = [f for f in rootdir.glob('**/*') if f.is_file()]

# For absolute paths instead of relative the current dir
file_list = [f for f in rootdir.resolve().glob('**/*') if f.is_file()]

从 Python 3.5 开始,该glob模块还支持递归文件查找:

import os
from glob import iglob

rootdir_glob = 'C:/Users/sid/Desktop/test/**/*' # Note the added asterisks
# This will return absolute paths
file_list = [f for f in iglob(rootdir_glob, recursive=True) if os.path.isfile(f)]

from上述file_list任何一种方法都可以在不需要嵌套循环的情况下进行迭代:

for f in file_list:
    print(f) # Replace with desired operations
于 2017-05-28T15:11:38.987 回答
20

从 python >= 3.5开始,您可以使用**glob.iglob(path/**, recursive=True)这似乎是最Pythonic的解决方案,即:

import glob, os

for filename in glob.iglob('/pardadox-music/**', recursive=True):
    if os.path.isfile(filename): # filter dirs
        print(filename)

输出:

/pardadox-music/modules/her1.mod
/pardadox-music/modules/her2.mod
...

注释:
1 - glob.iglob

glob.iglob(pathname, recursive=False)

返回一个迭代器,它产生的值与glob()没有同时存储它们的值相同。

2 - 如果递归是True,模式'**'将匹配任何文件和零个或多个directoriessubdirectories

3 - 如果目录包含以它们开头的文件 .,默认情况下不会匹配。例如,考虑一个包含 card.gif and的目录.card.gif

>>> import glob
>>> glob.glob('*.gif') ['card.gif'] 
>>> glob.glob('.c*')['.card.gif']

4 - 您也可以使用,这 与在给定的相对模式前面添加的rglob(pattern)调用相同 。glob()**/

于 2019-01-14T09:21:38.970 回答