0

我有一个包含许多文件的文件夹,我想将这些文件移入(要创建的)子文件夹(dump_1、dump_2、...),这样每个子文件夹都包含 100 个文件(或最后一个文件夹的剩余文件)。为了测试,我创建了像这样的小文本文件:

rootdir='d:/t2/'
for i in range(1000):
    f=open(rootdir+"file_"+str(i)+".txt","w")
    f.write("This is file "+str(i))
    f.close()

现在创建子文件夹和移动文件的代码是

import random
files=os.listdir(rootdir)
random.shuffle(files)
count=1
while files:
    newdir=(rootdir+"dump_"+str(count).zfill(2)+"/")
    os.mkdir(newdir)
    for a,b in enumerate(files):
            os.rename(rootdir+b,newdir+b)
            files.remove(b)
            if a==99:
                break
    count+=1

结果真的很奇怪:前 9 个文件夹包含所需的 100 个文件。但接下来的子文件夹包含 50、25、13、6、3、2 和 1 个文件。有谁知道为什么会这样以及我该如何解决?谢谢!

4

4 回答 4

1

Isn't it better to just iterate through the files and create new directory when necessary:

import random
files = os.listdir(rootdir)
random.shuffle(files)
count = 1
newdir = None
for filename in files:
    if count % 100 == 1 or newdir is None:
        newdir = rootdir + "dump_" + str(count).zfill(2) + "/"
        os.mkdir(newdir)
    os.rename(rootdir + filename, newdir + filename)
    count += 1

It saves cycles and makes the logic clear. Also, from the original I have not understood if batches should be 99 or 100 files. But it's easy to change 100 to 99. Also, there is no need to remove files from the list.

于 2012-08-04T19:29:17.353 回答
1

可能它与在其上方枚举的循环中更改变量“文件”有关。例如:

>>> l = [1,2,3,4,5,6,7,8,9]
>>> for a, b in enumerate(l):
...     l.remove(b)    
...     print a
... 
0
1
2
3
4

您可以在枚举中创建文件列表的副本(或拼接),例如

for a, b in enumerate(files[:100]):
于 2012-08-04T16:43:52.597 回答
0

非常感谢所有的帮助!我试图在下面的代码中组合所有这些,它运行起来就像一个魅力!

rootdir='d:/t2/'
import random
files = os.listdir(rootdir)
random.shuffle(files)
newdir = None
for n,filename in enumerate(files):
    if n%100 == 0 or newdir is None:
        newdir = rootdir + "dump_" + str(divmod(n,100)[0]).zfill(2) +"/"
        os.mkdir(newdir)
    os.rename(rootdir + filename, newdir + filename)
于 2012-08-05T19:22:23.487 回答
0

enumerate迭代列表的元素。作为生成器,它会在需要时进行每次迭代。现在在您的循环中,您正在从列表中删除项目,因为您仍在对其进行迭代。

这样,当您删除当前元素时,生成器在生成下一次迭代之前已经指向下一个元素。因此,它会跳过每一秒的条目:

>>> myList = [i for i in range(10)]
>>> for i, j in enumerate(myList):
        print(i, j)
        myList.remove(j)

0 0
1 2
2 4
3 6
4 8

现在您可以做的是为您的迭代创建一个副本,以便枚举本身不受删除的影响。另一种方法是改进整个循环,因此您实际上不需要从列表中删除元素。

于 2012-08-04T16:49:17.337 回答