通过os.walk进行目录递归,读取文件并找到文件中指定内容

本文介绍如何利用Python内置模块os中的walk方法遍历指定目录及其子目录下的所有文件,并筛选特定类型的文件进行关键字搜索,最后将搜索结果保存到新文件。

Mark:

通过os.walk进行整个文件目录的递归遍历,那么walk的语法如下:

walk()方法语法格式如下:

os.walk(top[, topdown=True[, onerror=None[, followlinks=False]]])

参数:

  • top -- 是你所要遍历的目录的地址, 返回的是一个三元组(root,dirs,files)。

    • root 所指的是当前正在遍历的这个文件夹的本身的地址
    • dirs 是一个 list ,内容是该文件夹中所有的目录的名字(不包括子目录)
    • files 同样是 list , 内容是该文件夹中所有的文件(不包括子目录)
  • topdown --可选,为 True,则优先遍历 top 目录,否则优先遍历 top 的子目录(默认为开启)。如果 topdown 参数为 True,walk 会遍历top文件夹,与top 文件夹中每一个子目录。

  • onerror -- 可选, 需要一个 callable 对象,当 walk 需要异常时,会调用。

  • followlinks -- 可选, 如果为 True,则会遍历目录下的快捷方式(linux 下是 symbolic link)实际所指的目录(默认关闭)。

注:该方法是没有返回值


当前使用os.walk代码遍历整个目录,并读取文件,找出文件内容的关键字,并写到指定文件中


# -*- coding: utf-8 -*-

import os

#遍历文件,查找后缀名为.m或者.h的文件,其它文件忽略不做检查
def findAllFiles(path):
    find_files = []
    for root, dirs, files in os.walk(path):   
        for file in files:
            pathWithFile = os.path.join(root,file)  #root当前文件路径本身+  file(查询到的文件名称)组成绝对路径
            if os.path.splitext(pathWithFile)[1] in [".m",".h"]:#指定查找以.m和.h的文件
                find_files.append(pathWithFile)
            else:
                pass
    return find_files


# read file
def readfile (readfilepath):

    keywords = ["#","//","/*","*","/**","*/"]  #搜索文件关键词

    with open(readfilepath,'r',encoding='utf-8') as f:  #使用with open方法打开文件,使用encoding参数主要解决文件内容为中文的问题
        newStr =[]
        for lines in f:
            for i in range(len(keywords)):
                if keywords[i] in lines:
                    newStr.append(lines)
    return newStr

def writeContent(writefilepath):
    getFilePath = findAllFiles("D:/test/mmm/")

    with open(writefilepath,'a',encoding='utf-8') as wf :
        for i in range(len(getFilePath)):
            getContent = readfile(getFilePath[i])
            for j in range(len(getContent)):
                gc = getContent[j]
                wf.write(gc)
    wf.close()


if __name__ == '__main__':
    testPath = "D:/test/Content.txt"
    writeContent(testPath)


<think>嗯,用户想用Python的os.walk来遍历指定路径下的所有文件,然后把它们复制到另一个文件夹里。首先,我需要回忆一下os.walk的用法。根据之前看到的引用资料,os.walk会返回一个三元组,包含当前目录的路径、子目录列表和文件列表。每次循环的时候,需要处理这些文件,逐个复制到目标文件夹。 用户提到的是复制所有文件,包括子目录中的文件。所以,需要保持目录结构吗?可能有两种情况:一种是保持原来的目录结构,复制到目标文件夹下;另一种是全部复制到目标文件夹的根目录下,不管原来的结构。但通常,保持目录结构比较合理。因此,在复制时,应该在目标路径中创建对应的子目录。 比如,当遍历到源路径下的某个子目录时,需要确定目标目录的路径。例如,源路径是/source,当前遍历的root是/source/subdir,那么目标目录应该是/target/subdir。这时候可能需要用os.path.relpath来获取相对路径,再结合目标文件夹生成新的路径。 然后,复制文件的话,可以使用shutil.copy2,这样能保留文件的元数据,比如修改时间。不过用户可能只需要内容,用shutil.copy也可以。但通常建议用copy2。 接下来,如何创建目标目录?对于每个文件,需要确保其目标目录存在。可以用os.makedirs(target_dir, exist_ok=True)来创建,这样即使目录已经存在也不会报错。 另外,用户可能还需要处理隐藏文件的问题。根据引用资料中的信息,os.walk默认会遍历所有文件目录,包括隐藏的。如果用户不希望复制隐藏文件,可能需要过滤掉以点开头的文件目录。比如在遍历时,检查文件名是否以.开头,如果是的话就跳过。不过用户的问题中没有特别提到这一点,可能不需要处理。不过可以作为一个注意事项提出来。 那具体的步骤应该是这样的: 1. 导入os和shutil模块。 2. 定义源路径和目标路径。 3. 使用os.walk遍历源路径。 4. 对于每个文件,构造源文件路径和目标文件路径。 5. 确保目标目录存在,创建必要的目录。 6. 复制文件。 例如,代码的大体结构可能是这样的: import os import shutil source = 'path/to/source' target = 'path/to/target' for root, dirs, files in os.walk(source): for file in files: src_path = os.path.join(root, file) # 获取相对路径,相对于source的部分 relative_path = os.path.relpath(root, source) dest_dir = os.path.join(target, relative_path) os.makedirs(dest_dir, exist_ok=True) dest_path = os.path.join(dest_dir, file) shutil.copy2(src_path, dest_path) 这样就能保持目录结构。不过需要考虑当source本身是绝对路径的情况,比如如果source是绝对路径,那么relpath可能会返回相对于当前工作目录的路径,而不是相对于source的。因此可能需要调整。或者,在遍历时,可能需要处理相对路径。 或者,可能应该将root与source进行比较,得到相对路径。例如,使用os.path.relpath(root, source),这样不管source是绝对还是相对路径,都能正确得到相对于source的路径部分。然后,将这个相对路径添加到target路径中,这样就能正确构建目标路径的结构。 例如,假设source是/parent/source,而当前root是/parent/source/subdir,那么relpath(root, source)就是subdir,所以目标目录是target/subdir。这样就正确保持了结构。 此外,还需要处理可能存在的权限问题,或者目标路径已经存在的文件是否覆盖。但用户可能只需要基本的复制,默认覆盖或者由操作系统处理。可以在代码中添加异常处理,但用户问题中没有提到,可能暂时不需要。 总结一下,核心步骤是遍历所有文件,构造目标路径,创建目录,复制文件。代码大致如上述示例。同时,可以提醒用户关于隐藏文件的问题,如果需要过滤的话,可以在files循环中添加条件判断,比如if not file.startswith('.'),或者在遍历dirs的时候修改dirs列表来排除隐藏目录(因为os.walk的dirs是引用传递,修改dirs会改变后续遍历的子目录)。 例如,在os.walk循环中,修改dirs列表,过滤掉以.开头的目录: for root, dirs, files in os.walk(source): # 过滤隐藏目录 dirs[:] = [d for d in dirs if not d.startswith('.')] # 过滤隐藏文件 for file in files: if file.startswith('.'): continue # 处理文件 这样就能跳过隐藏文件目录。不过用户的问题中没有特别说明是否需要,所以是否需要作为可选项提到? 另外,在代码中是否需要处理符号链接?如果用户需要复制链接本身还是指向的文件,可能需要用shutil.copy,但默认情况下shutil.copy会复制文件内容,而不是链接。如果用户需要保持符号链接,可能需要其他处理,但一般情况下可能不需要,所以可以暂时不考虑。 综上所述,给出一个完整的示例代码,解释每一步的操作,同时提醒可能的注意事项,如隐藏文件处理,目录结构保持等。</think>### 分步解决方案 使用Python的$os.walk$递归遍历目录复制文件到目标文件夹的实现步骤如下: --- #### **1. 导入必要模块** ```python import os import shutil ``` - $os$模块用于路径操作和目录遍历 - $shutil$模块提供文件复制功能 --- #### **2. 定义源路径和目标路径** ```python source_dir = "path/to/source" # 替换为实际源路径 target_dir = "path/to/target" # 替换为实际目标路径 ``` --- #### **3. 使用os.walk遍历源目录** ```python for root, dirs, files in os.walk(source_dir): # root: 当前遍历的目录路径 # dirs: 当前目录下的子目录列表 # files: 当前目录下的文件列表 ``` --- #### **4. 构建目标目录结构** ```python # 计算目标目录的相对路径 relative_path = os.path.relpath(root, source_dir) dest_path = os.path.join(target_dir, relative_path) # 创建目标目录(若不存在) os.makedirs(dest_path, exist_ok=True) ``` - $os.path.relpath$获取相对于源目录的相对路径[^3] - $os.makedirs$自动创建多层目录,$exist_ok=True$避免目录已存在时报错[^1] --- #### **5. 复制文件到目标目录** ```python for file in files: src_file = os.path.join(root, file) dst_file = os.path.join(dest_path, file) shutil.copy2(src_file, dst_file) ``` - $shutil.copy2$复制文件保留元数据(如修改时间) --- #### **完整代码** ```python import os import shutil def copy_all_files(source_dir, target_dir): for root, dirs, files in os.walk(source_dir): # 构建目标路径 relative_path = os.path.relpath(root, source_dir) dest_path = os.path.join(target_dir, relative_path) os.makedirs(dest_path, exist_ok=True) # 复制文件 for file in files: src_file = os.path.join(root, file) dst_file = os.path.join(dest_path, file) shutil.copy2(src_file, dst_file) # 调用示例 copy_all_files("path/to/source", "path/to/target") ``` --- #### **注意事项** 1. **过滤隐藏文件**: 在遍历时跳过以`.`开头的隐藏文件(Linux/macOS): ```python files = [f for f in files if not f.startswith('.')] dirs[:] = [d for d in dirs if not d.startswith('.')] # 修改dirs列表以跳过隐藏目录[^4] ``` 2. **符号链接处理**: $shutil.copy2$默认复制文件内容而非链接。若需保留符号链接,改用$os.symlink$。 3. **性能优化**: 大文件复制建议使用$shutil.copyfileobj$分块读取写入。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值