Python连接文本文件

我有一个20个文件名的列表,如['file1.txt', 'file2.txt', ...] 。 我想写一个Python脚本来连接这些文件到一个新的文件。 我可以通过f = open(...)打开每个文件,通过调用f.readline()读取,并将每行写入到新文件中。 对我来说,这看起来不是很“优雅”,尤其是我必须阅读的部分//逐行写。

在Python中有更“优雅”的方法吗?

这应该做到这一点

对于大文件:

 filenames = ['file1.txt', 'file2.txt', ...] with open('path/to/output/file', 'w') as outfile: for fname in filenames: with open(fname) as infile: for line in infile: outfile.write(line) 

对于小文件:

 filenames = ['file1.txt', 'file2.txt', ...] with open('path/to/output/file', 'w') as outfile: for fname in filenames: with open(fname) as infile: outfile.write(infile.read()) 

…和我想到的另一个有趣的

 filenames = ['file1.txt', 'file2.txt', ...] with open('path/to/output/file', 'w') as outfile: for line in itertools.chain.from_iterable(itertools.imap(open, filnames)): outfile.write(line) 

不幸的是,这最后一个方法留下了一些打开的文件描述符,GC应该照顾。 我只是觉得这很有趣

使用shutil.copyfileobj 。 它应该更有效率。

 with open('output_file.txt','wb') as wfd: for f in ['seg1.txt','seg2.txt','seg3.txt']: with open(f,'rb') as fd: shutil.copyfileobj(fd, wfd, 1024*1024*10) #10MB per writing chunk to avoid reading big file into memory. 

这正是文件input的目的:

 import fileinput with open(outfilename, 'w') as fout, fileinput.input(filenames) as fin: for line in fin: fout.write(line) 

对于这个用例来说,实际上并不比手动遍历文件简单得多,但是在其他情况下,将单个迭代器遍历所有文件就好像它们是单个文件一样,非常方便。 (另外, fileinput一旦完成就closures每个文件意味着不需要close或者close每个文件,但这只是一行节省,而不是一笔交易。)

fileinput还有一些非常漂亮的function,就像通过过滤每一行就能对文件进行就地修改一样。


正如在评论中指出的那样,并在另一篇文章中讨论,python 2.7的fileinput将不能正常工作。 这里做一些细微的修改,使代码Python 2.7兼容

 with open('outfilename', 'w') as fout: fin = fileinput.input(filenames) for line in fin: fout.write(line) fin.close() 

我不知道优雅,但这工作:

  import glob import os for f in glob.glob("file*.txt"): os.system("cat "+f+" >> OutFile.txt") 

UNIX命令有什么问题? (鉴于你不在Windows上工作):

ls | xargs cat | tee output.txt ls | xargs cat | tee output.txt完成这项工作(如果你愿意,你可以使用subprocess从python中调用它)

如果这些文件不是巨大的:

 with open('newfile.txt','wb') as newf: for filename in list_of_files: with open(filename,'rb') as hf: newf.write(hf.read()) # newf.write('\n\n\n') if you want to introduce # some blank lines between the contents of the copied files 

如果文件太大,无法在RAM中完全读取和保存,则algorithm必须稍微有点不同,以read(10000)为单位,以固定长度的块读取要循环复制的每个文件。

 def concatFiles(): path = 'input/' files = os.listdir(path) for idx, infile in enumerate(files): print ("File #" + str(idx) + " " + infile) concat = ''.join([open(path + f).read() for f in files]) with open("output_concatFile.txt", "w") as fo: fo.write(path + concat) if __name__ == "__main__": concatFiles() 

@ inspectorG4dget答案的替代方法(迄今为止的最佳答案29-03-2016)。 我testing了3个436MB的文件。

@ inspectorG4dget解决scheme:162秒

以下解决scheme:125秒

 from subprocess import Popen filenames = ['file1.txt', 'file2.txt', 'file3.txt'] fbatch = open('batch.bat','w') str ="type " for f in filenames: str+= f + " " fbatch.write(str + " > file4results.txt") fbatch.close() p = Popen("batch.bat", cwd=r"Drive:\Path\to\folder") stdout, stderr = p.communicate() 

这个想法是创build一个batch file并执行它,利用“老好技术”。 它的半python,但工作更快。 适用于windows。

如果目录中有很多文件,那么glob2可能是一个更好的选项,可以生成一个文件名列表,而不是手动编写它们。

 import glob2 filenames = glob2.glob('*.txt') # list of all .txt files in the directory with open('outfile.txt', 'w') as f: for file in filenames: with open(file) as infile: f.write(infile.read()+'\n') 

查看File对象的.read()方法:

http://docs.python.org/2/tutorial/inputoutput.html#methods-of-file-objects

你可以做这样的事情:

 concat = "" for file in files: concat += open(file).read() 

或更“优雅”的python方式:

 concat = ''.join([open(f).read() for f in files]) 

其中,根据这篇文章: http : //www.skymind.com/~ocrow/python_string/也将是最快的。