Comment traiter uniquement les nouveaux fichiers (non traités) sous Linux

Etant donné un répertoire avec un grand nombre de petits fichiers (> 1 mio), quel moyen rapide de mémoriser les fichiers déjà traités (pour une importation de firebase database).

La première solution que j’ai essayée était un 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 

Pour un échantillon plus petit (160 Ko), cela a duré environ 8 minutes (sans aucun traitement)

Ensuite, j’ai essayé un 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.ssortingp() 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) 

Cela fonctionne en moins de 2 minutes.

Existe-t-il un moyen beaucoup plus rapide que je ne le pense pas?

Autres solutions:

  • Déplacer des fichiers traités à des emplacements différents n’est pas pratique car j’utilise s3sync pour télécharger de nouveaux fichiers
  • Étant donné que les fichiers ont un horodatage dans leur nom, je peux envisager de les traiter dans l’ordre et de comparer uniquement le nom à une date de “dernier traitement”
  • sinon, je pouvais suivre la dernière exécution d’un traitement et ne traiter que les fichiers modifiés depuis.

Utilisez simplement un ensemble:

 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.ssortingp() 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) 

Approche alternative utilisant des utilitaires de ligne de commande standard:

diff juste un fichier contenant une liste de tous les fichiers avec un fichier contenant une liste de fichiers traités.

Facile à essayer et devrait être assez rapide.

Si vous incluez des horodatages complets dans la liste, vous pouvez également choisir des fichiers modifiés.

Si les fichiers ne sont pas modifiés après leur traitement, une option consiste à mémoriser le dernier fichier traité , puis à utiliser l’option -newer pour récupérer les fichiers non encore traités.

 find $rawdatapath -name '*.gz' -newer $( 

où process.sh ressemble à

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

Ceci n'a pas été testé. Surveillez les effets secondaires indésirables avant d'envisager de mettre en œuvre cette stratégie.

Si une solution hacky / quick'n'dirty est acceptable, une alternative géniale consiste à encoder l'état (traité ou non traité) dans les permissions de fichier , par exemple dans le bit d'autorisation de lecture de groupe. En supposant que votre umask est 022 , de sorte que tout fichier nouvellement créé dispose des permissions 644 , modifiez l'autorisation à 600 après avoir traité un fichier et utilisez l'option -perm pour récupérer les fichiers non encore traités.

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

où process.sh ressemble à

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

Encore une fois, cela n'a pas été testé. Surveillez les effets secondaires indésirables avant d'envisager de mettre en œuvre cette stratégie.