【问题标题】:Iteratively (or recursively?) filter directory and copy results to new directory迭代(或递归?)过滤目录并将结果复制到新目录
【发布时间】:2017-04-12 18:37:51
【问题描述】:

我是 Python 新手,一直在使用教科书和 StackOverflow 自学。我似乎从这个网站的真实世界例子中学到了最好的东西。我希望有人可以帮助我解决当前的问题。

我有一个包含大约 1,000 个文件的目录(文件夹)。这些文件的名称带有前缀(模式),例如aaa_*bbb_*ccc_* 等。我想遍历目录并复制所有具有指定前缀的文件并将它们移动到具有该前缀名称的新目录。例如,在/my_dir_path 中找到所有aaa_* 文件并将它们复制到/my_new_dir_path/aaa,同样将所有bbb_* 复制到/my_new_dir_path/bbb。新目录已创建。

以下简单的样板脚本可用于将前缀模式之一复制到新目录:

dir = '/my_dir_path'
pattern = 'aaa_*'
dest = '/my_new_dir_path/aaa'

for root, dirs, files in os.walk(dir):
    for filename in fnmatch.filter(files, pattern):
        source = (os.path.join(root, filename))
        shutil.copy2(source, dest)

我正在努力解决的是如何为我的模式列表递归运行fnmatch.filter,然后最终将文件输出到他们自己的目录。

我尝试编写了许多不同的函数定义,模式列表为*args,但通常会收到一条错误消息,即“filter() 恰好需要 2 个参数(3 个给定)”。 (很抱歉这里没有给你展示代码示例。最近几天我经历了很多版本,所以我没有任何一个有代表性的函数定义。)

我是个新手,我不知道 fnmatch.filter 是否可以递归或如何设计替代策略。然后,问题是如何将每个模式搜索的结果文件存储到自己的目录中。我在想我可以提前创建一个字典,例如,

my_dict = {'my_new_dir_path/aaa': 'aaa_*', 'my_new_dir_path/bbb': 'bbb_*'}

并将生成的文件作为值存储在适当的键下,但鉴于我什至还没有让递归工作(即打印),我还没有研究如何将结果复制到新目录。

【问题讨论】:

  • 我不清楚递归的期望结果。您是说要在多个级别移动文件吗?用公共前缀重命名目录?
  • 在原始目录中,有文件:aaa_1、aaa_2、aaa_n、bbb_4、bbb_6、bbb_7 等。我试图隔离所有那些是 'aaa_' 并复制/移动它们到一个标有“aaa”的文件夹,把所有的“bbb_”移到一个标有“bbb”的文件夹中。新目录(aaa、bbb 等)已经创建。

标签: python recursion filter directory os.walk


【解决方案1】:

现在我没有对此进行测试,因为我没有要测试的所有文件。但是,我只会将“模式”变量设为列表并添加另一个 for 循环。我还更改了“dest”变量,以便我们可以使用“模式”列表。

import os
import shutil
import fnmatch

dir = '/my_dir_path'
patterns = ['aaa', 'bbb', 'ccc']
dest = '/my_new_dir_path/'

for root, dirs, files in os.walk(dir):
    for pattern in patterns:
        for filename in fnmatch.filter(files, pattern+'_*'):
            source = (os.path.join(root, filename))
            shutil.copy2(source, dest+pattern+'/')

【讨论】:

  • 谢谢!第二个 for 循环完成了迭代。 (我把头撞在墙上,因为我用第二个 for 循环开始了这个过程。我现在知道我在哪里犯了错误。)现在的任务是隔离所有“a文件”并将它们复制到自己的dir (.../aaa) 并为 'b-files' --> (.../bbb) 等执行相同操作。目前,所有文件都被复制到单个目录。我想我需要将“for filename”循环的结果存储到一系列列表或字典中,这样我就可以将每个迭代复制到它自己的目录中。我现在将使用该代码。我很乐意接受建议。再次感谢。
  • 抱歉,我修正了我的代码中的一个错误。最初,我的最后一行是shutil.copy2(source, dest+'pattern'),它将所有文件放入一个名为“destination”的目录中。现在的行 (shutil.copy2(source, dest+pattern+'/')),它应该将文件放入它自己的目录中,无论它当前位于“模式”列表的哪个迭代中。这就是我在模式列表中省略“_*”的原因,所以它也可以用作目标目录的一部分。我还添加了 +'/' 来衡量。
  • 非常感谢您的帮助。那成功了。在我昨晚敲门之前,我意识到我需要添加+'/',但我没有注意到'pattern'(字符串)错误。我一直在使用各种代码版本,但它们都给出了相同的错误,因为模式被视为字符串。我已将此错误添加到我的 Python 错误清单中,以便在我对代码进行故障排除时查找。再次感谢您提供学习机会并为我节省了大量时间。
猜你喜欢
  • 2012-11-06
  • 2015-01-07
  • 2019-09-18
  • 2013-12-01
  • 2016-07-28
  • 2011-02-26
  • 2010-09-18
  • 1970-01-01
相关资源
最近更新 更多