为某些分析的输出重新创建输入文件夹树

Recreate input folder tree for output of some analyses

我是 Python 的新手,虽然到目前为止一直在阅读和享受它,但有 ∂ 经验,其中 ∂ → 0。

我有一个文件夹树,树枝底部的每个文件夹都包含许多文件。对我来说,input.

中的整棵树

我会执行几个分析步骤(我相信这些与这个问题无关),我希望在与输入相同的树中返回结果,称为 输出.

我有两个想法:

  1. 使用os.walk()递归读取每个文件夹并对每个文件执行分析,
  2. 使用 shutil.copytree() 之类的函数并在此过程中的某处执行分析。所以实际上,我根本不想复制树,而是复制它的结构,但使用新文件。我认为这可能是一种 'hack' 因为我实际上想要 使用 每个输入文件来创建输出文件,所以不是 copy 命令,我需要一个 analyse 命令。其他的就我想象中的理解范围而言应该保持不变。

我对选项 1 的经验很少,对选项 2 的经验为零。

到目前为止,对于较小的树,我一直在对路径进行硬编码,这在这一点上变得太耗时了。

我也看到了更多普通的方法,例如使用glob首先找到我想要的所有文件并处理它们,但我没有知道这如何帮助找到为我的输出重新创建输入树的捷径。

我对选项 1 的尝试如下所示:

import os

for root, dirs, files in os.walk('/Volumes/Mac OS Drive/Data/input/'):
    # I have no actual need to print these, it just helps me see what is happening
    print root, "\n"        
    print dirs, "\n"
    # This is my actual work going on
    [analysis_function(name) for name in files]

但是我担心这会很慢,我也想对文件进行某种过滤 - 例如在 mac 树中创建的 .DS_Store 文件包含在以上结果。我会尝试使用 fnmatch 模块来仅过滤我想要的文件。

我在 copytree 函数中看到可以根据模式忽略文件,这会很有帮助,但是我无法从文档中了解我可以将分析函数放在何处每个文件。

您可以使用这两个选项:您可以提供执行分析的自定义 copy_function 而不是默认 shutil.copy2shutil.copytree()(这更像是一种 hack)或者您可以使用 os.walk() 来更好地控制流程。

您不需要手动创建父目录。 copytree() 为您创建父目录,如果您使用 os.walk():

os.makedirs(root) 可以创建父目录
#!/usr/bin/env python2
import fnmatch
import itertools
import os

ignore_dir = lambda d: d in ('.git', '.svn', '.hg')
src_dir = '/Volumes/Mac OS Drive/Data/input/' # source directory
dst_dir = '/path/to/destination/'        # destination directory
for root, dirs, files in os.walk(src_dir):
    for input_file in fnmatch.filter(files, "*.input"): # for each input file
        output_file = os.path.splitext(input_file)[0] + '.output'
        output_dir = os.path.join(dst_dir, root[len(src_dir):])
        if not os.path.isdir(output_dir):
            os.makedirs(output_dir) # create destination directories 
        analyze(os.path.join(root, input_file), # perform analysis
                os.path.join(output_dir, output_file))

    # don't visit ignored subtrees
    dirs[:] = itertools.ifilterfalse(ignore_dir, dirs)