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

  1. #1
    Rédacteur/Modérateur

    Avatar de Roland Chastain
    Homme Profil pro
    Enseignant
    Inscrit en
    décembre 2011
    Messages
    3 507
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Enseignant

    Informations forums :
    Inscription : décembre 2011
    Messages : 3 507
    Points : 12 236
    Points
    12 236
    Billets dans le blog
    8
    Par défaut Doublons - Recherche et suppression de fichiers identiques sous Windows
    Bonjour ! Je vous propose un nouvel élément à utiliser :

    Doublons - Recherche et suppression de fichiers identiques sous Windows

    J'avais un dossier d'images (des photos plus exactement) dont certaines étaient en double ou en triple, mélangées et éparpillées dans des sous-dossiers différents, et sous des noms différents. J'avais donc besoin d'un programme qui détecte les doublons et les élimine. Voilà la fonction de ce programme, qui est proposé sous plusieurs formes. À vous de choisir celle qui pourrait correspondre à vos besoins.

    Qu'en pensez-vous ?

  2. #2
    Membre chevronné

    Homme Profil pro
    au repos
    Inscrit en
    février 2014
    Messages
    428
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : au repos

    Informations forums :
    Inscription : février 2014
    Messages : 428
    Points : 1 878
    Points
    1 878
    Par défaut
    Bonjour Roland.

    Programme utile (surtout demo5) et, dans ton code, j'ai trouvé une ou deux fonctions dont j'ignorais l'existence.
    Merci à toi.

    Cordialement
    Thierry

    PS : je vais devoir mettre à jour l'unité ThDialogs qui a été écrite à l'époque où Lazarus n'utilisait pas les fichiers .res ---> plantage actuel avec les ressources images.

  3. #3
    Membre éclairé
    Avatar de FOCUS77
    Homme Profil pro
    Développeur informatique
    Inscrit en
    août 2014
    Messages
    334
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : Algérie

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Agroalimentaire - Agriculture

    Informations forums :
    Inscription : août 2014
    Messages : 334
    Points : 661
    Points
    661
    Par défaut
    Bonsoir T.W,

    Citation Envoyé par ThWilliam Voir le message
    PS : je vais devoir mettre à jour l'unité ThDialogs qui a été écrite à l'époque où Lazarus n'utilisait pas les fichiers .res ---> plantage actuel avec les ressources images.
    .


    Bonne nouvelle, pour ma part je désire avoir une 'QuestionDlg' ayant cet aspect si c'est possible.

    img:
    Nom : QuestionDlg.png
Affichages : 1445
Taille : 19,0 Ko

  4. #4
    Membre averti
    Profil pro
    Inscrit en
    avril 2010
    Messages
    190
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : avril 2010
    Messages : 190
    Points : 426
    Points
    426
    Par défaut
    Bonjour,

    Merci pour ce code. Pour ma part, j'ai surtout été intéressé par la demo_4 qui permet de rechercher des doublons, même lorsque les noms sont différents. J'ai modifié les ancrages de différents champs pour permettre à l'utilisateur d'ajuster les dimensions de la fiche à la liste des noms de fichiers qui s'affichent et donné la possibilité de comparer des répertoires différents.
    Probablement sans importance sur le résultat (il doit être exceptionnel d'avoir un fichier de plus de 4 Go), mais il me semble que le calcul de la taille des fichiers est erroné.
    La taille est obtenue à partir des parties haute et basse d'un vData:TWin32FindData par la formule:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    vData.nFileSizeHigh * MaxDWord + vData.nFileSizeLow //MaxDWord=$FFFFFFFF
    devrait être
    (vData.nFileSizeHigh shl 32)or vData.nFileSizeLow
    D'autre part la comparaison de 2 fichiers à partir de leur chargement total dans 2 TMemoryStream m’inquiète un peu. Ne risque-t-on pas de débordement mémoire en comparant 2 gros fichiers? (ce qu'un utilisateur peut ignorer avant de lancer la recherche).
    Aussi j'ai préféré modifier la fonction CompareFiles pour que la comparaison se fasse par blocs de 10Mo maxi:
    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
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    function CompareFiles(const aFirstFileName,aSecondFileName:string): boolean;
    const
      TailleMax=10000000;
    var
      ms1,ms2:TMemoryStream;
      F1,F2:TFileStream;
      L,M,T:Int64;
    begin
      Result:=False;
     
      if FileExists(aFirstFileName) and FileExists(aSecondFileName) then
      begin
        F1:=TFileStream.Create(aFirstFileName,fmOpenRead);
        try
          F2:=TFileStream.Create(aSecondFileName,fmOpenRead);
          try
            T:=F1.Size;
            if T=F2.Size then
            begin;
              ms1:=TMemoryStream.Create;
              ms2:=TMemoryStream.Create;
              try
                F1.Position:=0;
                F2.Position:=0;
                L:=0;
                repeat
                  if (T-L)>TailleMax then
                    M:=TailleMax
                  else
                    M:=T-L;
                  Inc(L,M);
                  ms1.CopyFrom(F1,M);
                  ms2.CopyFrom(F2,M);
                  ms1.Position := 0;
                  ms2.Position := 0;
                  Result:=CompareMem(ms1.Memory,ms2.Memory,M);
                until not Result or (L>=T);
              finally
                ms2.Free;
                ms1.Free;
              end;
            end;
          finally
            F2.Free;
          end;
        finally
          F1.Free;
        end;
      end;
    end;
    André

  5. #5
    Rédacteur/Modérateur

    Avatar de Roland Chastain
    Homme Profil pro
    Enseignant
    Inscrit en
    décembre 2011
    Messages
    3 507
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Enseignant

    Informations forums :
    Inscription : décembre 2011
    Messages : 3 507
    Points : 12 236
    Points
    12 236
    Billets dans le blog
    8
    Par défaut
    Bonjour !

    Merci pour vos retours.

    Citation Envoyé par alanglet Voir le message
    Probablement sans importance sur le résultat (il doit être exceptionnel d'avoir un fichier de plus de 4 Go), mais il me semble que le calcul de la taille des fichiers est erroné.
    Ah oui, bien vu. J'avais trouvé dans des discussions lues ici et là les deux formules et j'ai cru paresseusement qu'elles étaient équivalentes : je m'aperçois que ce n'est pas le cas.

    Citation Envoyé par alanglet Voir le message
    D'autre part la comparaison de 2 fichiers à partir de leur chargement total dans 2 TMemoryStream m’inquiète un peu. Ne risque-t-on pas de débordement mémoire en comparant 2 gros fichiers ?
    Effectivement. Le problème a été évoqué dans cette discussion. J'aurais dû utiliser l'une des procédures par blocs.

    Citation Envoyé par ThWilliam Voir le message
    PS : je vais devoir mettre à jour l'unité ThDialogs qui a été écrite à l'époque où Lazarus n'utilisait pas les fichiers .res ---> plantage actuel avec les ressources images.
    Effectivement, je m'en étais aperçu. Nous attendons avec impatience la nouvelle version.

  6. #6
    Expert confirmé
    Avatar de anapurna
    Homme Profil pro
    Développeur informatique
    Inscrit en
    mai 2002
    Messages
    2 913
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Arts - Culture

    Informations forums :
    Inscription : mai 2002
    Messages : 2 913
    Points : 4 785
    Points
    4 785
    Par défaut
    salut,

    j'ai regardé un peu le code

    le fait de parcourir tout les sous répertoire pour chaque fichier afin de trouver un doublon n'est pas super optimisé

    J'aurais parcouru les répertoires pour enregistrer chaque fichier dans une liste d'enregistrement du type
    genre

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    TFichierData = record
            nom     : string;
            dossier : string;
            date    : integer;
            taille  : integer;
            use     : boolean;
        end;
    le parcourt se ferait comme ceci

    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
     
    Function FindOwnAllFiles(AFolder,AExt: String;Recursif : Boolean) : TListFichier;
     
      procedure RechercherFichiers(Lst : TListFichier ;NomDossier,exten : string ; Recursif : Boolean );
      var
        hFind : TSearchRec;
      begin
        NomDossier := slach(NomDossier);  // Attention au '\' ;-)
        if FindFirst( NomDossier + exten, FaAnyFile, hFind ) = 0 then
        begin
          repeat
            if (hFind.Name <> '.') and (hFind.Name <> '..') then
            begin
              { c'est un fichier on l'ajoute a la structure }
              if ( hFind.Attr and faDirectory ) <> faDirectory then
                Lst.AddEnreg( hFind.Name, NomDossier, hFind.Size, hFind.Time ) // Ajoute fichier à la liste
              else { c'est un dossier on va voir dedans }
                if Recursif Then
                  RechercherFichiers(Lst,(slach(NomDossier) + hFind.Name),exten,Recursif);
            end;
          until FindNext(hFind) <> 0;
          Application.ProcessMessages;
          FindClose(hFind);
        end;
      end;
     
    begin
      result := TListFichier.Create;
      RechercherFichiers(result,AFolder,AExt,Recursif);
    end;
    J'aurais trié cette liste par taille
    et ensuite si les fichiers on la même taille j'aurais fait la comparaison et enregistrer dans une deuxième liste de fichiers dupliqués
    Nous souhaitons la vérité et nous trouvons qu'incertitude. [...]
    Nous sommes incapables de ne pas souhaiter la vérité et le bonheur, et sommes incapables ni de certitude ni de bonheur.
    Blaise Pascal
    PS : n'oubliez pas le tag

  7. #7
    Rédacteur/Modérateur

    Avatar de Roland Chastain
    Homme Profil pro
    Enseignant
    Inscrit en
    décembre 2011
    Messages
    3 507
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Enseignant

    Informations forums :
    Inscription : décembre 2011
    Messages : 3 507
    Points : 12 236
    Points
    12 236
    Billets dans le blog
    8
    Par défaut
    @anapurna

    Merci pour ta remarque. En effet, j'ai choisi la solution de facilité et non pas la plus efficace. Quand j'aurai le temps, j'essaierai d'appliquer la méthode que tu proposes.

Discussions similaires

  1. [Batch] Recherche et suppression de fichiers windows 2003
    Par gagouk dans le forum Scripts/Batch
    Réponses: 16
    Dernier message: 12/06/2012, 08h11
  2. Réponses: 3
    Dernier message: 22/04/2010, 17h12
  3. Réponses: 2
    Dernier message: 17/01/2010, 01h01
  4. Afficher un fichier binaire sous Windows
    Par Atomikx dans le forum x86 32-bits / 64-bits
    Réponses: 4
    Dernier message: 14/12/2004, 00h29

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