【问题标题】:Iterating through directories with Python使用 Python 遍历目录
【发布时间】:2023-08-08 06:49:01
【问题描述】:

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

我试过了:

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

但我收到错误消息。我究竟做错了什么?

【问题讨论】:

  • “一个错误” - 有什么特别的错误吗?
  • 请您解释一下,一旦您按预期工作后,您希望如何处理文件/目录?另请提供错误详情。
  • 我得到的错误信息是找不到文件cool.txt。在我的测试文件夹中,我有一个名为 src 的文件夹,在 src 文件夹中,我有另一个名为 main 的文件夹,在这个文件夹中,我有 cool.txt
  • 你能把错误写在问题里吗?必须通读 cmets 才能找到它,这非常烦人且不必要。
  • 一年多后,我不敢相信我回来要求发布错误? @狼

标签: python directory


【解决方案1】:

实际浏览目录的过程与您编写的代码相同。如果你用简单的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))

【讨论】:

  • C:/Users/sid/Desktop/test\src\app/cool.txt C:/Users/sid/Desktop/test\src\app/woohoo.txt 雅在打开声明我的代码,我想我必须给出文件的绝对路径。 import os rootdir ='C:/Users/spemmara/Desktop/test/src/app/' for subdir, dirs, files in os.walk(rootdir): for file in files: f=open(subdir+'/'+ file ,'r') lines=f.readlines() f.close() f=open(subdir+'/'+file,'w') for line in lines: newline = "hey i know" f.write(newline) f.close() 谢谢伙计。解决了
  • 先生,我收到 IsADIrectoryError
【解决方案2】:

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

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

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

for f in file_list:
    print(f) # Replace with desired operations

【讨论】:

  • 这里对于 Python 3.6 有什么更好的选择?
  • @PhoenixDev 我还没有听说过一种方法被推荐而不是另一种方法。我更喜欢自己使用pathlib,主要是因为我喜欢面向对象的方法语法。还有其他差异,例如路径库返回特定的路径类而不是字符串,并且库之间的可用函数不同(例如os.path.expanduser('~') vs Path.home())。浏览文档并查看您喜欢哪种方法。
  • 您可以使用rglob,而不是在全局模式中添加**
  • 在你的代码中,rootdir_glob 到底是干什么用的? O.o 它只是一个完整的路径示例吗?顺便说一句:短版:import os, glob + file_list = [f for f in glob.iglob('**/*', recursive=True) if os.path.isfile(f)]
  • @joelostblom 哦,我建议也使用os 来创建跨平台路径:) - 无论如何,基于你的这个想法,我今天创建了一个小工具来计算 中的所有文件N 目录树及其大小,因此您可以快速进行一些基本的完整性预检查 - 我已在 ideone.com/4pu1qs 上发布它 - prints() 中有一些“错别字”,但除此之外它可以作为魅力:)
【解决方案3】:

从 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.card.gif 的目录:

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

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

【讨论】:

  • 这个 pythonic 解决方案没有列出隐藏文件(又名 dotfiles),而被接受的却有。
  • @ashrasmun 您提到的内容在docs.python.org/3/library/glob.html中得到了很好的解释