复制所有特定扩展名的文件,同时保持目录结构

6 投票
3 回答
7000 浏览
提问于 2025-04-19 13:50

我的问题

  1. 遍历一个文件夹,找到所有的头文件,也就是以 *.h 结尾的文件。
  2. 把这些文件复制到另一个地方,同时保持原来的文件夹结构。

我尝试过的

我已经使用 os 库成功找到了所有的头文件。

for root, dirs, files in os.walk(r'D:\folder\build'):
    for f in files:
        if f.endswith('.h'):
            print os.path.join(root, f)

这段代码正确地打印出了:

D:\folder\build\a.h
D:\folder\build\b.h
D:\folder\build\subfolder\c.h
D:\folder\build\subfolder\d.h

我卡住的地方

现在我有了一份完整的文件路径列表,接下来我该怎么做才能把这些文件复制到另一个地方,同时保持子文件夹的结构呢?在上面的例子中,我希望能保持 \build\ 下面的目录结构。

比如,我希望复制后能创建如下结构:

D:\other\subfolder\build\a.h
D:\other\subfolder\build\b.h
D:\other\subfolder\build\subfolder\c.h
D:\other\subfolder\build\subfolder\d.h

3 个回答

1

这段代码会把当前文件夹中所有以“.h”结尾的文件,递归地复制到目标文件夹(dest_dir)里,而且不会在目标文件夹里创建任何子文件夹。

import glob
import shutil
from pathlib import Path

# ignore any files but files with '.h' extension
for file in glob.glob('**/*.h', recursive=True):
    shutil.copyfile(
        Path(file).absolute(), 
        (Past(dest_dir)/Path(file).name).absolute()
    )
2

编辑:正如 @pchiquet 所示,这个操作可以用一个命令完成。不过我会展示一下如何手动处理这个问题。

你需要准备三样东西。

你知道你正在浏览哪个目录,所以为了构建目标路径,你需要把源目录的名字换成目标目录的名字:

walked_directory = 'D:\folder\build'
found_file = 'D:\other\subfolder\build\a.h'
destination_directory = 'D:\other\subfolder'
destination_file = found_file.replace('walked_directory', 'destination_directory')

现在你有了源路径和目标路径,首先你需要确保目标路径是存在的:

os.makedirs(os.path.dirname(destination_file))

一旦目标路径存在,你就可以开始复制文件了:

shutil.copyfile(found_file, destination_file)
9

你可以使用 shutil.copytree 这个函数,并且配合一个 ignore 的可调用对象来过滤要复制的文件。

"如果提供了 ignore,它必须是一个可调用的对象,这个对象会接收两个参数:一个是正在被 copytree() 访问的目录,另一个是这个目录下的文件列表 (...). 这个可调用对象需要返回一个目录和文件名的序列,这些名字是相对于当前目录的(也就是说,是第二个参数中的一部分);这些名字在复制过程中会被忽略掉"

所以针对你的具体情况,你可以这样写:

from os.path import join, isfile
from shutil import copytree

# ignore any files but files with '.h' extension
ignore_func = lambda d, files: [f for f in files if isfile(join(d, f)) and f[-2:] != '.h']
copytree(src_dir, dest_dir, ignore=ignore_func)

撰写回答