我有一个包含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
输出:
Traceback (most recent call last):
File "filterimage.py", line 13, in <module>
filenames = os.listdir(dir+'labels/')
OSError: [Errno 12] Cannot allocate memory: '/somedir/'
这是修改过的脚本:
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
它适用于文件较少的文件夹,但对于较大的文件夹,所有打印的文件都是“0”... 在linux服务器上运行,在mac上打印0 ...哦......好吧......
答案 0 :(得分:4)
您可以尝试使用返回迭代器的glob.iglob
:
topdir = os.path.join('/somedir', 'labels', '*')
for filename in glob.iglob(topdir):
if filelen(filename) > 15:
#do stuff
此外,请不要将dir
用于变量名称:您正在隐藏内置函数。
您可以介绍的另一项重大改进是filelen
功能。如果用以下内容替换它,您将节省大量时间。相信我,what you have now is the slowest alternative:
def many_line(fname, many=15):
for i, line in enumerate(open(fname)):
if i > many:
return True
return False
答案 1 :(得分:2)
几个想法。首先,您可以使用glob
模块来获取较小的文件组。其次,按行计数排序将非常耗时,因为您必须打开每个文件并计算行数。如果可以按字节计数进行分区,则可以使用stat
模块来避免打开文件。如果分割发生在20行是至关重要的,那么你至少可以通过计算出你的类型的20行文件所具有的最小字符数来减少大量文件,而不是打开任何小于该行的文件。 / p>
答案 2 :(得分:0)
import os,shutil
os.chdir("/mydir/")
numlines=20
destination = os.path.join("/destination","dir1")
for file in os.listdir("."):
if os.path.isfile(file):
flag=0
for n,line in enumerate(open(file)):
if n > numlines:
flag=1
break
if flag:
try:
shutil.move(file,destination)
except Exception,e: print e
else:
print "%s moved to %s" %(file,destination)
答案 3 :(得分:0)
如何使用shell脚本?你可以一次选择一个文件:
for f in `ls`;
loop
if `wc -l f`>20; then
mv f newfolder
fi
end loop
如果我错了,请纠正
答案 4 :(得分:0)
目前接受的答案只是简单不起作用。这个功能:
def many_line(fname, many=15):
for i, line in enumerate(line):
if i > many:
return True
return False
有两个问题:首先,fname
arg未使用且文件未打开。其次,对enumerate(line)
的调用将失败,因为line
未定义。
将enumerate(line)
更改为enumerate(open(fname))
会解决问题。
答案 5 :(得分:0)
您可以使用os.scandir这是一个生成器,因此不会一次读取所有文件名(python 3.5附带,否则,或者只是读取:pip install scandir)。
示例:
import os
for file in os.scandir(path):
do_something_with_file(path+file.name)
scandir文档:https://pypi.org/project/scandir/