IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Langage Perl Discussion :

Conseil pour un script de suppression de fichiers en double


Sujet :

Langage Perl

  1. #1
    Expert confirmé
    Avatar de doc malkovich
    Homme Profil pro
    Consultant en Business Intelligence
    Inscrit en
    Juillet 2008
    Messages
    1 884
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Nord (Nord Pas de Calais)

    Informations professionnelles :
    Activité : Consultant en Business Intelligence

    Informations forums :
    Inscription : Juillet 2008
    Messages : 1 884
    Points : 4 285
    Points
    4 285
    Billets dans le blog
    1
    Par défaut Conseil pour un script de suppression de fichiers en double
    Hello,

    Tout d'abord je vous préviens : venant du décisionnel je suis un très grand débutant en perl ! Un vrai noob
    Donc je m'excuse par avance si jamais il existe déjà une solution clé en main (google n'est pas toujours mon ami ).

    Et je vous explique mon problème :
    Je voudrais faire un script qui supprime les fichiers en doublons.
    En gros je donne un répertoire que je connais et qui est à jour, et je choisis d'autres répertoires où le programme va me donner les doublons parfaits ou presque. Bien sûr les critères peuvent varier, cela peut être la taille, la date, un CRC ou les métadonnées du fichier.

    Voici comment je comptais faire :
    1. Scanner le répertoire de référence et lister les fichiers
    2. Créer un fichier A listant les fichiers, avec au début de chaque ligne la ou les clés de comparaison, puis les infos sur le fichier (répertoire+nom)
    3. Trier ce fichier A
    4. Créer un fichier B de la même façon pour les autres répertoires à comparer
    5. Parcourir les 2 fichiers en parallèle
    6. Si on a la même clé dans l'un et l'autre on traite le fichier trouvé dans B (suppression ou déplacement)


    Vous en pensez quoi ?
    Ne connaissant pas Perl je ne suis pas sûr que ce soit la meilleure méthode ; j'avoue avoir pris là un algo un peu passepartout qui ne prend pas forcément en compte les avantages et subtilités du langage.
    Utiliser les tableaux ou tables de hachage ne me semble pas judicieux car la volumétrie peut être importante et les clés ne sont pas forcément uniques (sauf à faire des tables de tableaux).
    Des conseils ?

    Merci
    A+
    Doc
    N'oubliez pas de cliquer sur lorsque votre problème est réglé !

  2. #2
    Rédacteur/Modérateur

    Avatar de Lolo78
    Homme Profil pro
    Conseil - Consultant en systèmes d'information
    Inscrit en
    Mai 2012
    Messages
    3 612
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Conseil - Consultant en systèmes d'information
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Mai 2012
    Messages : 3 612
    Points : 12 256
    Points
    12 256
    Billets dans le blog
    1
    Par défaut
    1. Dans ton répertoire de référence, tes noms de fichiers sont forcément unique.

    2. Qu'entends-tu par volumétrie importante? J'aurais du mal à croire que ton répertoire de référence contienne des millions de fichiers.

    Bref, au vu de mes questions, tu auras peut-être deviné que je préconise un tableau de hachage, avec comme clef le nom du fichier, et comme valeur la taille, le CRC, ce que tu veux utiliser.

    Tu charges dans le hachage les informations relatives aux fichiers du répertoire de référence, puis parcours les autres répertoires et compare les informations. L'avantage est que la recherche dans un tableau de hachage ne dépend pas de la taille du tableau (elle est en O(1)), c'est réellement hyper-rapide.

  3. #3
    Expert confirmé
    Avatar de doc malkovich
    Homme Profil pro
    Consultant en Business Intelligence
    Inscrit en
    Juillet 2008
    Messages
    1 884
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Nord (Nord Pas de Calais)

    Informations professionnelles :
    Activité : Consultant en Business Intelligence

    Informations forums :
    Inscription : Juillet 2008
    Messages : 1 884
    Points : 4 285
    Points
    4 285
    Billets dans le blog
    1
    Par défaut
    J'ai oublié de dire que le répertoire de référence pouvait contenir des sous-répertoires
    Et donc oui je peux avoir une volumétrie importante
    Et les noms de fichier ne sont pas uniques.

    Pour replacer dans le contexte, c'est pour faire du ménage dans mes fichiers, mais je n'ai pas trouvé de solution clés en main satisfaisante ...

    Si je reprends ton principe je peux faire une table de hachage avec en clé la clé de comparaison ( par exemple concaténation de nom + taille + date ) et en valeur d'autres infos.
    Mais est-ce viable avec une volumétrie importante ?
    N'oubliez pas de cliquer sur lorsque votre problème est réglé !

  4. #4
    Membre régulier
    Homme Profil pro
    Inscrit en
    Janvier 2009
    Messages
    71
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Janvier 2009
    Messages : 71
    Points : 87
    Points
    87
    Par défaut
    bonjour,

    question bête, je n'ai jamais a utilisé ce genre de programme, mais ne serait-il pas plus simple de comparer le contenu directement avec un md5?

    http://perldoc.perl.org/Digest/MD5.html

    une table de hash avec comme clé la valeur du md5 et en valeur le ou les noms des doublons avec leur chemin "en dur" par exemple

    et a chaque nouveau fichier listé, on calcule le md5, s'il n existe pas, on l'ajoute,
    s'il existe, on compare et demande confirmation avant de le supprimer.

    enfin, n'ayant jamais eu a m’intéresser a ce genre de choses, je dis peut-être une énorme ânerie.

    cordialement

    ours

  5. #5
    Expert confirmé
    Avatar de doc malkovich
    Homme Profil pro
    Consultant en Business Intelligence
    Inscrit en
    Juillet 2008
    Messages
    1 884
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Nord (Nord Pas de Calais)

    Informations professionnelles :
    Activité : Consultant en Business Intelligence

    Informations forums :
    Inscription : Juillet 2008
    Messages : 1 884
    Points : 4 285
    Points
    4 285
    Billets dans le blog
    1
    Par défaut
    Oui on peut faire ça, c'est ce que je sous-entendais avec le CRC.

    Mais il faut lire tout le fichier pour calculer son empreinte ... ça prend du temps

    Merci
    doc
    N'oubliez pas de cliquer sur lorsque votre problème est réglé !

  6. #6
    Membre chevronné Avatar de dmganges
    Homme Profil pro
    Retraité. Ne recherche pas un emploi.
    Inscrit en
    Septembre 2011
    Messages
    1 392
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 71
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Retraité. Ne recherche pas un emploi.
    Secteur : Service public

    Informations forums :
    Inscription : Septembre 2011
    Messages : 1 392
    Points : 2 044
    Points
    2 044
    Par défaut
    Bjr,
    Si Perl que j’apprécie beaucoup est redoutable en puissance, il n'est peut-être pas adapté pour cette manip.
    Perso, je ne vois une solution bourrin :
    1 - Lire l'arborescence, stocker les infos utiles dans une table de base de données MSQL, Oracle... avec les index au bon endroit : Nom, chemin (répertoire), date, taille... evt droit d'accès...
    2 - Lire la table ligne par ligne (select *), pour chaque ligne générer éventuellement un delete sur un [select interne] qui ramène la plus petite date du groupe.

    Tu trouveras quelques bons exemples d'accès à une base (MSQL ou Oracle) en Perl ici

    C'est bourrin, pas très difficile à mettre en œuvre, hors mis la requête SQL delete si tu ne connais pas SQL.

    Si cette piste te convient, autrement dit si tu as la possibilité d'accéder à une base (pour moi de préférance Oracle), pour y créer une table temporaire, je peux approfondir le sujet... éventuellement faire quelques essais en local..

    @+

  7. #7
    Expert confirmé
    Avatar de doc malkovich
    Homme Profil pro
    Consultant en Business Intelligence
    Inscrit en
    Juillet 2008
    Messages
    1 884
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Nord (Nord Pas de Calais)

    Informations professionnelles :
    Activité : Consultant en Business Intelligence

    Informations forums :
    Inscription : Juillet 2008
    Messages : 1 884
    Points : 4 285
    Points
    4 285
    Billets dans le blog
    1
    Par défaut
    Hello,

    j'ai un profil décisionnel donc je me débrouille en sql on va dire

    Au niveau perfs si tu connais oracle j'essaierai d'éviter au maximum les nested loops sur les index. Quand on parcourt toute une table il vaut mieux faire un full scan et par exemple prendre les opérateurs MINUS ou INTERSECT ; c'est en cela que je m'inspirais avec mon 1er algo.
    Mais bon, je ne pense pas avoir des milliards de lignes non plus

    Le passage par une bdd me plaît bien dans le sens où je peux stocker les données pour les réutiliser après, et puis c'est un milieu connu pour moi. Et ça n'a pas l'air très compliqué d'y acccéder en perl d'après le lien que tu donnes

    Merci
    Doc
    N'oubliez pas de cliquer sur lorsque votre problème est réglé !

  8. #8
    Membre chevronné Avatar de dmganges
    Homme Profil pro
    Retraité. Ne recherche pas un emploi.
    Inscrit en
    Septembre 2011
    Messages
    1 392
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 71
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Retraité. Ne recherche pas un emploi.
    Secteur : Service public

    Informations forums :
    Inscription : Septembre 2011
    Messages : 1 392
    Points : 2 044
    Points
    2 044
    Par défaut
    ben c'est gagné

    (Pour les personnes qui suivent :
    S'il y a un index sur le nom de fichier, ce qui est indispensable pour le sélect interne, (sinon n puissance n lectures), il faut mettre un HINT sur le 1er select ligne à ligne pour éviter le nested loops.)

    Pardonne-moi, "décisionnel" ne veut pas nécessairement dire pour moi féru en BDD...
    Dans ton cas, tu vas résoudre le pb avant ce soir !
    Slt !

  9. #9
    Rédacteur/Modérateur

    Avatar de Lolo78
    Homme Profil pro
    Conseil - Consultant en systèmes d'information
    Inscrit en
    Mai 2012
    Messages
    3 612
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Conseil - Consultant en systèmes d'information
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Mai 2012
    Messages : 3 612
    Points : 12 256
    Points
    12 256
    Billets dans le blog
    1
    Par défaut
    Si tu as plusieurs fois le même nom de fichier, dans des sous-répertoires différents, de ton répertoire de référence, est-ce à dire que le répertoire que tu compares doit avoir au moins en partie la même arborescence? C'est à dire que si tu as plusieurs fichiers "toto.txt", tu compares réellement "./sub_dir1/sub_dir2/toto.txt" entre ton répertoire de référence et ton répertoire à vérifier?

  10. #10
    Rédacteur/Modérateur

    Avatar de Lolo78
    Homme Profil pro
    Conseil - Consultant en systèmes d'information
    Inscrit en
    Mai 2012
    Messages
    3 612
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Conseil - Consultant en systèmes d'information
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Mai 2012
    Messages : 3 612
    Points : 12 256
    Points
    12 256
    Billets dans le blog
    1
    Par défaut
    Voici un exemple utilisant un hash (%reference) pour stocker la taille des fichiers, puis comparant la taille des fichiers à vérifier avec celles stockées dans le hash.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    use strict;
    use warnings;
     
    my %reference;
    chomp @ARGV;
    my ($dir_depart, $dir_a_comparer) = @ARGV;
     
    parcours_dir(\&alimente_ref, $dir_depart);
    print "Prise de ref terminee. Debut comparaison. \n";
    parcours_dir(\&compare_ref, $dir_a_comparer);
     
    print "Nombre de fichiers de ref: ", scalar keys %reference, "\n";
     
    sub parcours_dir {
    	my ($code_ref, $path) = @_;
    	my @dir_entries = glob("$path/*");
    	foreach my $entry (@dir_entries) {
    		$code_ref->($entry) if -f $entry;
    		parcours_dir($code_ref, $entry) if -d $entry;
    	}
    }
     
    sub alimente_ref {
         my $fichier = shift;
         $reference{$fichier} = -s $fichier;
    }
     
    sub compare_ref {
    	my $fichier = shift;
    	print "fichiers différents: $fichier \n" if 
                 (not exists $reference{$fichier})
                 or $reference{$fichier} != -s $fichier;
    }
    Voici une exécution en passant deux fois le même répertoire en paramètre:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    $ time perl parcourt_dir2.pl "/usr" "/usr"
    Prise de ref terminee. Debut comparaison.
    Nombre de fichiers de ref: 27124
     
    real    0m18.023s
    user    0m3.119s
    sys     0m14.897s
    Le programme a mis 18 secondes pour lire la taille 27124 fichiers, la stocker dans un hachage, puis relire la taille de 27124 fichiers et la comparer à la taille stockée dans le hachage (sur mon PC portable, pas un gros serveur survitaminé).

    Les fichiers sont stockés avec le chemin (donc pas de problème de doublon). Par exemple, le programme a stocké dans le hachage /usr/bin/perl et sa taille.

    En passant des répertoires différents:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    $ time perl parcourt_dir2.pl "/usr" "."
    Prise de ref terminee. Debut comparaison.
    fichiers différents: ./2_lines.pl
    fichiers différents: ./a.pl
    fichiers différents: ./analyse_fable.pl
    ...
    En l'état ce programme ne répond pas vraiment à ton besoin, un ou deux petits changements seraient encore nécessaires, mais je voulais juste montrer que l'on pouvait gérer un nombre respectable de fichiers en un temps limité. Et l'accès à un hachage (en mémoire) est bien plus rapide que l'accès à une base de données.

  11. #11
    Expert confirmé
    Avatar de doc malkovich
    Homme Profil pro
    Consultant en Business Intelligence
    Inscrit en
    Juillet 2008
    Messages
    1 884
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Nord (Nord Pas de Calais)

    Informations professionnelles :
    Activité : Consultant en Business Intelligence

    Informations forums :
    Inscription : Juillet 2008
    Messages : 1 884
    Points : 4 285
    Points
    4 285
    Billets dans le blog
    1
    Par défaut
    Merci Laurent pour ce code, ça m'éclaire beaucoup sur la façon de faire en Perl (très concise) et ça me donne un bon squelette de programme

    Et pour répondre à ta question précédente, non je ne compare avec l'arborescence ; si j'ai plusieurs fichiers toto.txt je compare juste avec la taille et la date, voire le crc ou md5.

    encore !
    N'oubliez pas de cliquer sur lorsque votre problème est réglé !

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Script de suppression de fichier
    Par yessam75 dans le forum Shell et commandes POSIX
    Réponses: 4
    Dernier message: 06/10/2011, 08h48
  2. Script de suppression de fichier
    Par lokomass dans le forum Shell et commandes POSIX
    Réponses: 2
    Dernier message: 23/09/2011, 16h58
  3. script de suppression de fichiers dans une arborescence
    Par linuxman dans le forum VBScript
    Réponses: 7
    Dernier message: 14/05/2010, 09h37
  4. Besoin de quelques conseils pour un script java
    Par poussin544 dans le forum Général JavaScript
    Réponses: 7
    Dernier message: 02/03/2006, 10h41
  5. Script de suppression de fichiers en fonction de la date
    Par yellow174 dans le forum Langages de programmation
    Réponses: 2
    Dernier message: 06/02/2006, 11h57

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo