如何在Linux中只处理新的(未经处理的)文件

给定一个包含大量小文件(> 1 mio)的目录,记住哪些文件已经被处理(用于数据库导入)是一种快速的方法。

我尝试的第一个解决scheme是一个bash脚本:

#find all gz files for f in $(find $rawdatapath -name '*.gz'); do filename=`basename $f` #check whether the filename is already contained in the process list onlist=`grep $filename $processed_files` if [[ -z $onlist ]] then echo "processing, new: $filename" #unzip file and import into mongodb #write filename into processed list echo $filename #>> $processed_files fi done 

对于一个较小的样本(160k文件),这运行了大约8分钟(没有任何处理)

接下来我尝试了一个python脚本:

 import os path = "/home/b2blogin/webapps/mongodb/rawdata/segment_slideproof_testing" processed_files_file = os.path.join(path,"processed_files.txt") processed_files = [line.strip() for line in open(processed_files_file)] with open(processed_files_file, "a") as pff: for root, dirs, files in os.walk(path): for file in files: if file.endswith(".gz"): if file not in processed_files: pff.write("%s\n" % file) 

这运行不到2分钟。

有没有一个明显更快的方式,我俯瞰?

其他解决scheme

  • 因为我使用s3sync来下载新文件,所以将处理的文件移动到不同的位置是不方便的
  • 由于文件有一个时间戳作为他们的名字的一部分,我可能会考虑依靠处理它们的顺序,只比较名称与“最后处理”的date
  • 或者我可以跟踪上一次处理的运行,并且只处理自那以后被修改过的文件。

只要使用一套:

 import os path = "/home/b2blogin/webapps/mongodb/rawdata/segment_slideproof_testing" processed_files_file = os.path.join(path,"processed_files.txt") processed_files = set(line.strip() for line in open(processed_files_file)) with open(processed_files_file, "a") as pff: for root, dirs, files in os.walk(path): for file in files: if file.endswith(".gz"): if file not in processed_files: pff.write("%s\n" % file) 

使用标准命令行工具的替代方法:

只需将包含所有文件列表的文件与包含已处理文件列表的文件进行比较即可。

易于尝试,而且应该相当快。

如果您在列表中包含完整的时间戳,则可以通过这种方式获取“已更改”的文件。

如果文件在处理后没有被修改,一个选项是记住最新的处理文件 ,然后使用find-newer选项来检索尚未处理的文件。

 find $rawdatapath -name '*.gz' -newer $(<latest_file) -exec process.sh {} \; 

process.sh看起来像

 #!/bin/env bash echo "processing, new: $1" #unzip file and import into mongodb echo $1 > latest_file 

这是未经测试的。 在考虑实施这一战略之前,应该注意不必要的副作用。

如果一个hacky / quick'n'dirty解决方案是可以接受的, 一个时髦的选择是编码状态(处理或不处理)的文件权限 ,例如在组读取权限位。 假设你的umask022 ,所以任何新创建的文件都有权限644 ,在处理文件后将权限改为600 ,并使用find-perm选项来检索尚未处理的文件。

 find $rawdatapath -name '*.gz' -perm 644 -exec process.sh {} \; 

process.sh看起来像

 #!/bin/env bash echo "processing, new: $1" #unzip file and import into mongodb chmod 600 $1 

这再次没有经过测试。 在考虑实施这一战略之前,应该注意不必要的副作用。