2014-05-12 12 views
5

Data una directory con un numero elevato di file di piccole dimensioni (> 1 mio), un modo veloce per ricordare quali file sono già stati elaborati (per l'importazione di un database).Come elaborare solo nuovi file (non elaborati) in linux

La prima soluzione che ho provato era uno script 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 

Per un campione più piccolo (160K file) questo ha funzionato ~ 8 minuti (senza alcun trattamento)

Poi ho provato uno script 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) 

Questo funziona in meno di 2 minuti.

C'è un modo significativamente più veloce che sto trascurando?

Altre soluzioni:

  • Moving file elaborati a un diverso posizioni non è conveniente dal momento che usare s3sync per scaricare nuovi file
  • dal momento che i file hanno un timestamp come parte del loro nome potrei prendere in considerazione per fare affidamento sull'elaborazione degli stessi in ordine e confrontare solo il nome con una data "ultima elaborazione"
  • in alternativa, è possibile tenere traccia dell'ultima volta che è stata eseguita un'elaborazione e elaborare solo i file che sono stati modificati successivamente.
+1

il tempo di tracciamento sarebbe probabilmente il più veloce – redFIVE

risposta

5

Basta utilizzare un set:

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

piacerebbe vedere una figura su come questo accelera le cose – Nicolas78

+0

Grande - questo l'ha portato da 120 a 0.5 s – Cilvic

2

approccio alternativo utilizzando utility a riga di comando standard:

Basta diff un file contenente un elenco di tutti i file con un file contenente un elenco di trattati File.

Facile da provare, e dovrebbe essere abbastanza veloce.

Se si include la data e l'ora complete nell'elenco, è possibile selezionare anche i file 'modificati' in questo modo.

1

Se i file non vengono modificati dopo che sono stati elaborati, una possibilità è quella ricordare l'ultimo file elaborato e quindi utilizzare l'opzione find s' -newer per recuperare i file non ancora processati.

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

dove process.sh sembra

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

Questo è testato. Cercare effetti collaterali indesiderati prima di considerare l'implementazione di questa strategia.

Se una soluzione hacky/quick'n'dirty è accettabile, uno funky alternativa è quella di codificare lo stato (trasformate o non trasformati) nelle autorizzazioni file, per esempio nel gruppo di leggere bit di permesso.Supponendo che il tuo umask sia 022, in modo che qualsiasi file appena creato disponga delle autorizzazioni 644, modifica l'autorizzazione per 600 dopo l'elaborazione di un file e utilizza l'opzione per recuperare i file non ancora elaborati.

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

dove process.sh sembra

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

Anche questo è testato. Cercare effetti collaterali indesiderati prima di considerare l'implementazione di questa strategia.

+0

Mi piace la creatività di quello, grazie per le idee! – Cilvic

Problemi correlati