【问题标题】:For every x number of files; create new directory and move files -- using Python对于每 x 个文件;创建新目录并移动文件——使用 Python
【发布时间】:2012-09-24 04:59:05
【问题描述】:

我有一个包含几千个文件的目录。我希望能够在较大的导演内创建子目录,并将 150 个文件(按扩展名过滤)移动到每个新创建的目录中。我希望得到一些指导来帮助我前进。这是我要开始的小事:

wd = os.chdir(r'foobar')

allgzs=[]

for file in os.listdir(wd):
    if file.endswith('asc.gz'):
       allgzs.append(file)

for gz in allgzs:


# For every 150 .gz files: 
# Create directory -- os.mkdir?
# Move files into directory  -- shutil.move?

【问题讨论】:

    标签: python directory move shutil


    【解决方案1】:

    我想出了一个grouper 函数来在n 的运行中产生一个长序列:

    import itertools
    def grouper(S, n):
        iterator = iter(S)
        while True:
            items = list(itertools.islice(iterator, n))
            if len(items) == 0:
                break
            yield items
    

    从那里,你可以非常简洁地做你想做的事:

    import glob, os, shutil
    fnames = sorted(glob.glob('*asc.gz'))
    for i, fnames in enumerate(grouper(fnames, 150)):
        dirname = 'batch%d' % i
        os.mkdir(dirname)
        for fname in fnames:
            shutil.move(fname, dirname)
    

    【讨论】:

    • 你可能不需要sorted,但os.listdirglob.glob对我来说都是以伪随机顺序出现的,这让我觉得非常不直观,所以我在我的例子中添加了它。
    【解决方案2】:

    让我们看看,我会列举在这种情况下我会做什么。

    • 获取文件列表 - X
    • 循环遍历所有文件 - X
    • 确保文件只有一个句点 - O
    • 过滤掉不需要的扩展 - X
    • 将想要的扩展添加到新列表 - O
    • 遍历新列表中的所有文件 - O
    • 将它们添加到列表中并使用计数器,以便知道何时有 150 - O
    • 当您有 150 个文件时,将它们全部移动 - O
    • 回到循环 - O
    • 遍历所有内容并复制后,您就完成了。

    你有它。此外,这绝不是最有效或最好的方法,我就是这样做的。

    编辑:示例代码:

    wantedexts = [".jpg",".png",".randomext"]
    wantedfiles = []
    
    for f in files: #the files from the folder
        allowedext = 0
        for exts in wantedexts:
            if f.endswith(exts):
                allowedext = 1
                break
        if allowedext:
            wantedfiles.append(f)
    
    counter = 0
    countertwo = 0 #used to tell when you get to the end of the files
    copyfiles = []
    for f in wantedfiles:
        if counter == 150 or countertwo == len(wantedfiles):
            for fc in copyfiles:
                copy    #too lazy to type in real copy code
            counter = 0
            copyfiles = []
        copyfiles.append(f)
        counter += 1
        countertwo += 1
    

    几乎为您编写了代码,但无论如何。 Countertwo 用于复制最后的项目(因为可能会剩下一些)。

    【讨论】:

    • 感谢工作流程大纲,这真的很有帮助。你能详细说明一下柜台吗?
    • 嗯,这确实是我编造的一个术语,虽然它是一个计数器。基本上它是循环外的整数(因此每次循环时它都不会重置)。因此,对于循环通过的每个文件,将 1 添加到计数器。您在循环中做的第一件事是检查计数器是否为 150。如果是,则移动文件,然后继续循环的正常操作。如果你愿意,我可以提供示例代码。
    • 那太棒了。阅读您的工作流程后,我还编辑了操作
    • 没问题的人,祝项目好运。另请查看其他一些答案,他们有更有效的方法来做某些事情。我的方式只是一个自学成才的程序员的标志。
    【解决方案3】:

    如果您热衷于保留已经编写的代码,这里有一个直观的方式来完成它:

    import os
    import shutil
    
    wd = os.chdir(r'foobar')
    
    allgzs=[]
    
    for file in os.listdir(wd):
        if file.endswith('asc.gz'):
           allgzs.append(file)
    
    n = 1
    name = "subdir%i" %n
    for gz in allgzs:
        if not os.path.exists(name):
            os.mkdir(name)
        shutil.move(gz, name)
        if len(os.listdir(name)) == 150:
            n += 1
            name = "subdir%i" %n
    

    【讨论】:

    • 您现在应该直接在示例中导入osshutil,而不是单独提醒(注意:它是“shutil”,而不是“shutils”)。跨度>
    • 是的。谢谢你的建议。
    • @MuMind 感谢您考虑我的问题。我正在尝试实现您的示例,它第一次可以工作,但在if len(os.listdir(foo))OSError: [Errno 20] Nota directory: foo 的第二次迭代中失败了有什么想法吗?
    • @Karol 我认为该评论是给你的,而不是我。
    • @Karol 是的,我向 Mu Mind 道歉,这个问题是针对你的。知道为什么 name 约定在一次迭代之后就不起作用了吗?
    【解决方案4】:

    我只是在这里使用列表推导来制作文件名列表。您的列表将来自 os.listdirglob.glob('*asc.gz')

    >>> files = ['foo{}.gz'.format(i) for i in range(5000)]
    >>> for i, fname in enumerate(files):
    ...     if i%150 == 0:
    ...         dirname = "bar{}".format(i//150)
    ...         os.mkdir(dirname)
    ...     print fname,"-->", dirname
    ...     shutil.move(fname, dirname)
    ... 
    foo0.gz --> bar0
    foo1.gz --> bar0
    foo2.gz --> bar0
    foo3.gz --> bar0
    foo4.gz --> bar0
    foo5.gz --> bar0
    ... 
    

    这里的技巧是记录我们正在处理的文件的数量并除以150 以将其映射到目录中。 // 仅表示整数除法(与 Python2 中的 / 相同)

    【讨论】:

      【解决方案5】:

      您可以为此使用glob 模块

      for file in glob.glob('*.gz'):
          #Do Stuff
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2018-12-30
        • 2020-09-11
        • 1970-01-01
        • 1970-01-01
        • 2018-04-07
        • 2019-10-17
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多