2014-05-12 69 views
5

給定一個包含大量小文件(> 1 mio)的目錄,記住哪些文件已被處理(用於數據庫導入)的快速方法是什麼?如何僅在Linux中處理新(未處理)文件

我嘗試的第一個解決方案是一個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分鐘。

有沒有一種明顯更快的方式,我忽略了?

其他的解決方案:

  • 移動處理的文件到不同的位置並不方便,因爲我用s3sync下載新的文件
  • 因爲文件有一個時間戳,我可能會考慮到他們的名字的一部分依靠對它們進行處理,只將名稱與「最後處理」日期進行比較
  • 或者我可以跟蹤上一次處理運行的時間,並且只處理自那之後修改過的文件。
+1

跟蹤時間可能會是最快的 – redFIVE

回答

5

只需使用一組:

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) 
+1

很想看到這個如何加快速度的數字 – Nicolas78

+0

太好了 - 這從120s降到了0.5s – Cilvic

2

替代方法使用標準的命令行實用程序:

只是diff包含所有文件的列表包含的處理的列表文件的文件文件。

易於嘗試,並且應該相當快。

如果您在列表中包含全部時間戳,您也可以通過這種方式選取「已更改」文件。

1

如果它們被處理後的文件不被修改,一個選擇是記住最新處理的文件然後用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 

這是未經測試。在考慮實施這一策略之前,應查看不需要的副作用。

如果哈克/ 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 

再次,這是未經測試。在考慮實施這一策略之前,請注意不需要的副作用。

+0

我喜歡這個創意,謝謝你的想法! – Cilvic