Contenu | Rechercher | Menus

Annonce

Si vous avez des soucis pour rester connecté, déconnectez-vous puis reconnectez-vous depuis ce lien en cochant la case
Me connecter automatiquement lors de mes prochaines visites.

À propos de l'équipe du forum.

#1 Le 13/12/2017, à 08:42

DonutMan75

[RESOLU] Idée d'algo pour transfert de fichier automatique ?

Bonjour à tous,
j'ai un script de transfert de fichier via lftp qui récupère des .zip depuis un serveur distant.
Ce serveur contient plusieurs milliers de fichier .zip et évolue lentement (deux ou trois nouveaux fichiers par jours, certains fichiers sont susceptibles d'être supprimés)

Voici mon algo :

- téléchargement des .zip dans le répertoire ./download via lftp en mode miroir
- dans les logs du lftp précédent, je récupère les nouveaux fichiers transférés (par un 'grep Transferring') et je les dézippe dans le répertoire ./data (et uniquement ceux là)

Bref, j'étais tout content de mon script vu que je ne dézippe que quelques fichiers à chaque exécution : les nouvellement transférés.

Oui mais il y a un gros effet de bord : si côté serveur un fichier zip est supprimé alors :
- ce même fichier est bien supprimé de mon répertoire local ./download (option miroir de lftp...)
- en revanche, les fichiers dézippés associés sont eux toujours présent dans ./data !!!

J'ai beau chercher et regarder les options de lftp, je ne vois pas du tout comment résoudre ce problème simplement...

J'espérais une option "move" dans lftp pour déplacer les fichiers obsolètes plutôt que de les supprimer, mais tout ce que j'ai trouvé c'est l'option ci-dessous qui ne semble pas répondre à mon besoin...

man lftp a écrit :

--Move                     same as --Remove-source-dirs
--Remove-source-dirs       remove source files and directories  after  transfer
                                                (use  with  caution).   Top  level  directory is not
                                                removed if it's name ends with a slash.

Un truc auquel j'ai pensé c'est éventuellement de lancer une première commande en mode dry-run (option --dry-run) pour faire quels fichiers sont susceptibles d'être supprimés, puis de supprimer leur contenu de ./data et enfin de lancer la vraie commande lftp... A supposer que dans l'intervalle de temps, l'état du serveur n'évolue pas....

Vous auriez une idée géniale ou une suggestion ?

Merci d'avance et bonne journée smile

Donut

Dernière modification par DonutMan75 (Le 13/12/2017, à 13:53)

Hors ligne

#2 Le 13/12/2017, à 10:04

bruno

Re : [RESOLU] Idée d'algo pour transfert de fichier automatique ?

Bonjour,

C'est peut-être une bêtise mais lftp mirror ne supprime pas les fichiers. S'il le fait c'est que tu l'as précisé avec une option.

L'idée serait donc de ne pas spécifier l'option delete, lancer l'opération avec lftp miror, comparer la liste des fichiers locaux et distants (via ls ou via des logs de lftp plus bavards) et se baser sur cette comparaison pour déplacer les fichiers locaux obsoleetes.

Hors ligne

#3 Le 13/12/2017, à 13:50

DonutMan75

Re : [RESOLU] Idée d'algo pour transfert de fichier automatique ?

Bonjour Bruno,
Bien vu !
Je n'avais pas réalisé mais en effet, par défaut mirror ne supprime pas les fichiers obsolètes mais mentionne juste dans les logs quelque chose comme :

Old file `/data/toto.ZIP' is not removed

Mon algo est ainsi le suivant (je suis en train de le valider).
J'ai utilisé l'option -l de unzip qui permet de connaître l'ensemble des fichiers contenu dans le zip (sans dézipper).
Bon par contre par défaut ça affiche une sortie du genre ci-dessous :

$unzip -l test.zip
Archive:  test.zip
  Length      Date    Time    Name
---------  ---------- -----   ----
   810000  05-07-2014 15:09   file1.txt
   810000  05-07-2014 15:09   file2.txt
   810000  05-07-2014 15:09   file3.txt
---------                     -------
  2430000                     3 files

J'ai donc du faire un grep/awk un peu sale pour récupérer uniquement les noms de fichiers sans formatage particulier (je ne pense pas qu'il soit possible de faire autrement ?). Ca m'ennuie un peu parce que le man de unzip dit que le formatage de sortie dépend des versions de unzip ==> mon awk n'est donc pas du tout portable... sad

Enfin, voici mon code ci-dessous. Je vous le donne pour mémoire (et aussi pour partager un peu ^^) mais je pense que le sujet est résolu. Si vous avez des remarques ou des commentaires, je serai ravi de l'améliorer ^^

process_folder() {
NAME=$1 		# Nom du produit à récupérer
REMOTE_FOLDER=$2 	# Chemin distant
ZIP_FOLDER=$3 		# Répertoire local contenant les zip
EXTRACTED_FOLDER=$4 	# Répertoire local contenant les fichiers dézippés

# Ce code se connecte au serveur distant et récupère l'ensemble des fichiers ZIP contenu dans $REMOTE_FOLDER
# Il en fait un miroir dans le dossier local $ZIP_FOLDER
# Il extrait ensuite les nouveaux ZIP (et uniquement ceux-là) dans $EXTRACTED_FOLDER
# Enfin il supprime les anciens ZIP (et uniquement ceux-là) de $ZIP_FOLDER ainsi que les fichiers associés ayant été dézippés dans $EXTRACTED_FOLDER

echo "- Downloading new $NAME products..."
lftp ftp://$USER:$PASS@$HOST -e "mirror --no-perms --verbose=1 $REMOTE_FOLDER ${ZIP_FOLDER%/} ; quit"  | tee -a $FTMP1
if [ $? -ne 0 ] ; then fatal "lftp error while downloading $NAME products" ; fi

# On ne garde que la liste des fichiers effectivement transférés ET se terminant en .ZIP (case insensitive)
grep -E '^Transferring' $FTMP1 | grep -i "ZIP'$" | sed -re "s+^.*\`(.*)'$+\1+" > "$FTMP2"

if [ -s "$FTMP2" ] ; then # Il existe au moins un nouveau ZIP...
	echo "- Extracting new $NAME products in the relevant directory..."

	while read f ; do
		# unzip -j (junk path, pas de sous-rep), -o (force overwrite)
		unzip -j -o -d "${EXTRACTED_FOLDER}" "${ZIP_FOLDER}$f"
	done < "$FTMP2"
fi

# On supprime les fichiers n'existant plus côté serveur...
grep -E '^Old file' $FTMP1 | grep -i "ZIP' is not removed$" | sed -re "s+^.*\`(.*)'.*$+\1+" > "$FTMP2"

if [ -s "$FTMP2" ] ; then # Il existe au moins un ancien ZIP...
	# On construit la liste des fichiers à supprimer côté dézippé et zippé
	echo "- Deleting outdated $NAME products..."
	while read fzip ; do
		unzip -l "$fzip"| grep "SW" | grep -vi "ZIP" | awk '{print $4}' > "$FTMP3"
	
		while read fold ; do
			if [ -e ${EXTRACTED_FOLDER}${fold} ] ; then
				echo "  - Deletion of ${EXTRACTED}${fold} from ${ZIP_FOLDER}${fzip}"
				#rm -rf ${EXTRACTED_FOLDER}${fold}
			else
				warn "Failed to delete ${EXTRACTED_FOLDER}${fold} file (file not found)"
			fi
		done < "$FTMP3"	
		echo "  - Deletion of ${ZIP_FOLDER}${fzip}"
		#rm -rf "${ZIP_FOLDER}${fzip}"
	done < "$FILEIST2"
fi

# Suppression des fichiers temporaires
rm -rf "$FTMP1"
rm -rf "$FTMP2"
rm -rf "$FTMP3"
}

Merci d'avance pour vos retours smile

Donut

Dernière modification par DonutMan75 (Le 13/12/2017, à 13:52)

Hors ligne

#4 Le 13/12/2017, à 14:58

bruno

Re : [RESOLU] Idée d'algo pour transfert de fichier automatique ?

Ravi si j'ai pu t'être utile et merci pour le partage de code wink

Pour voir uniquement la liste des fichiers d'une archive zip, tu peux utiliser :

zipinfo -1 toto.zip

Hors ligne

#5 Le 13/12/2017, à 15:09

DonutMan75

Re : [RESOLU] Idée d'algo pour transfert de fichier automatique ?

Hello,
je ne connaissais pas du tout zipinfo, en effet c'est bien plus propre comme ça !
Je laisse tourner mon code pour voir si tout se passe bien.
Merci encore pour le coup de main.

Bonne aprem à tous,

Donut

Hors ligne