使用Python遍历目录


157

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

我尝试了这个:

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

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


12
“错误”-特别是任何错误?
Daniel Roseman

1
一旦逐步了解文件/目录的工作原理,您能否对它们做些解释?还请提供错误详细信息。
ChrisProsser 2013年

1
即时消息错误消息是找不到文件cool.txt。在我的测试文件夹中,我有另一个名为src的文件夹,在src文件夹中有另一个名为main的文件夹,在此文件夹中,我具有cool.txt
Wolf

4
您可以只在问题中写下错误吗?它很烦人,也不必阅读注释才能找到它。
查理·帕克

1
一年多以后,我无法相信我会再要求发布该错误?@狼
查理·帕克

Answers:


300

实际遍历目录的工作方式与您对代码的编码方式相同。如果用简单的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))

1
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 /'用于subdir,dirs,os.walk(rootdir)中的文件:用于文件中的文件:f = open(subdir +'/'+文件,'r')lines = f.readlines()f.close()f = open(subdir +'/'+ file,'w')换行:newline =“嘿我知道” f.write(newline) f.close()谢谢你。解决了
沃尔夫

3
嗨!请记住,Python 3中的“打印”需要括号,否则会返回语法错误。希望这可以帮助!
托马索·迪诺托

14

返回子目录中所有文件的另一种方法是使用Python 3.4中引入pathlib模块模块提供了一种面向对象的方法来处理文件系统路径(Pathlib在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('**/*', recursive=True) if os.path.isfile(f)]

file_list从任一上述方法可被遍历,而不需要一个嵌套循环:

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

1
对于Python 3.6,这里首选什么?
PhoenixDev

@PhoenixDev我还没有听说过一般推荐一种方法。我更喜欢使用pathlib自己,主要是因为我喜欢面向对象的方法语法。还有其他区别,例如路径库返回特定的路径类而不是字符串,并且库之间的可用函数有所不同(例如os.path.expanduser('~')vs Path.home())。浏览文档,查看您喜欢哪种方法。
joelostblom

**您可以使用代替添加glob模式rglob
乔治,

12

截至2020年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() 与**/在给定相对模式前面添加调用相同  。


1
这种pythonic解决方案不会列出隐藏文件(也就是点文件),而被接受的文件却不会列出。
ashrasmun

@ashrasmun您提到的内容在docs.python.org/3/library/glob.html中
CONvid19
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.