过滤非常大的文件夹中的文件

ext*_*eee 6 python file-io

我有一个包含100k文本文件的文件夹.我想把超过20行的文件放在另一个文件夹中.我怎么在python中这样做?我使用了os.listdir,但当然没有足够的内存来将文件名加载到内存中.有没有办法一次获得100个文件名?

这是我的代码:

import os
import shutil

dir = '/somedir/'

def file_len(fname):
    f = open(fname,'r')
    for i, l in enumerate(f):
        pass
    f.close()
    return i + 1

filenames = os.listdir(dir+'labels/')

i = 0
for filename in filenames:
    flen = file_len(dir+'labels/'+filename)
    print flen
    if flen > 15:
        i = i+1
        shutil.copyfile(dir+'originals/'+filename[:-5], dir+'filteredOrigs/'+filename[:-5])
print i
Run Code Online (Sandbox Code Playgroud)

并输出:

Traceback (most recent call last):
  File "filterimage.py", line 13, in <module>
    filenames = os.listdir(dir+'labels/')
OSError: [Errno 12] Cannot allocate memory: '/somedir/'
Run Code Online (Sandbox Code Playgroud)

这是修改后的脚本:

import os
import shutil
import glob

topdir = '/somedir'

def filelen(fname, many):
    f = open(fname,'r')
    for i, l in enumerate(f):
        if i > many:
            f.close()
            return True
    f.close()
    return False

path = os.path.join(topdir, 'labels', '*')
i=0
for filename in glob.iglob(path):
    print filename
    if filelen(filename,5):
        i += 1
print i
Run Code Online (Sandbox Code Playgroud)

它适用于文件较少的文件夹,但是文件夹较大,所有打印的文件都是"0"...在linux服务器上运行,在Mac上打印0 ...哦......

Sil*_*ost 4

您可以尝试使用glob.iglob返回迭代器:

topdir = os.path.join('/somedir', 'labels', '*')
for filename in glob.iglob(topdir):
     if filelen(filename) > 15:
          #do stuff
Run Code Online (Sandbox Code Playgroud)

另外,请不要使用dir变量名:您正在隐藏内置变量。

您可以引入的另一个主要改进是您的filelen功能。如果您将其替换为以下内容,您将节省大量时间。相信我,你现在拥有的是最慢的选择

def many_line(fname, many=15):
    for i, line in enumerate(open(fname)):
        if i > many:
            return True
    return False
Run Code Online (Sandbox Code Playgroud)