Fil sammenligning/sammenføring

Tags:    csharp net

Godaften

Jeg har et problem med at jeg ofte har haft kopieret filer fra min telefon, og fra mit ekstra kort.
Problemet heri er så at jeg nu har en masse forskellige mapper med backup versioner fra forskellige dato'er med forskellige mapper og filer i. Nogle er de samme, nogle har flere end andre, nogle har færre men andre ting.

Nu vil jeg så lave et program der kan sammenligne filerne på navn og filstørrelse, og hvis den finder samme fil/størrelse/oprettet-redigeret-dato, så putte dem på en beslutningsliste som jeg skal tage stilling til hvad der skal ske med.

Problemet er så bare at strukturmæssigt er jeg usikker på hvordan jeg laver den mest optimalt?

Så man skal kunne tilføje flere sources den skal forsøge at samle i en destination, og de ens filer skal der så tages stilling til.
Tænker noget med en hashtabel så man nemt kan lave opslag på hver fil om den tidligere er fundet, men med forskellige mappe strukturer skal det jo selvfølgelig også kunne lave det.

Hvad foreslår i?

Måske ikke lige sådan en helt lige til og lidt mere avanceret spørgsmål, men synes det er svært at få lavet en god struktur i mit hoved, så lad mig høre erfaringer og foreslag.



8 svar postet i denne tråd vises herunder
2 indlæg har modtaget i alt 6 karma
Sorter efter stemmer Sorter efter dato
Har ingen erfaringer det problem, men her er nogle løse tanker.

Dit problem ligger lidt op ad en meget light udgave af et versionskontrolsystem. Som jeg forstår problemet er det at tage en mængde af mappestrukturer og finde frem til en enkelt mappestruktur.

Lad os antage du har fundet en gruppe (f.eks. i en List<T> ) af filer du mener er den samme fil i forskellige udgaver. Den gruppe bliver nu opdelt i flere grupper hvis der er afvigelser i f.eks. størrelse eller dato. Sorter filerne efter attributter de ikke må afvige på for at være den samme. Det er attributter på størrelse, dato og så videre. Hvis to filer har samme størrelse, sorterer du i stedet efter dato, osv.. Det er ligegyldigt hvilken attribut du prioriterer først, og om du ordner efter "<" eller ">", f.eks. om datoen er tidligere eller senere. (note: hvis 2 filer har samme størrelse kan det være nødvendigt at læse dem igennem for at se om de er ens.)

Nu er det nemt at indsætte dem i ækvivalensrelationer, dvs. grupper som er ens. Vælg den første fil i den sorterede liste, og check den op mod resten. Så snart den afviger tager du alle dem du nåede at checker om i mod, og smider i en collection. Så fortsætter du med resten. Her er et eksempel med nogle filer der er den "samme":

MappeA\Sti\MinDataFil.extension, 19kB, 17/06
MappeB\Sti\MinDataFil.extension, 21kB, 14/06
MappeC\Sti\MinDataFil.extension, 19kB, 17/06
MappeD\Sti\MinDataFil.extension, 21kB, 15/06
MappeE\Sti\MinDataFil.extension, 19kB, 16/06

Efter du har sorteret, størrelse først, derefter dato.

MappeE\Sti\MinDataFil.extension, 19kB, 16/06
MappeA\Sti\MinDataFil.extension, 19kB, 17/06
MappeC\Sti\MinDataFil.extension, 19kB, 17/06
MappeB\Sti\MinDataFil.extension, 21kB, 14/06
MappeD\Sti\MinDataFil.extension, 21kB, 15/06

Nu kan de så inddeles i ækvivalensrelationer. Vi bliver ved med at "tage" indtil attributterne varierer:

1:
MappeE\Sti\MinDataFil.extension, 19kB, 16/06

2:
MappeA\Sti\MinDataFil.extension, 19kB, 17/06
MappeC\Sti\MinDataFil.extension, 19kB, 17/06

3:
MappeB\Sti\MinDataFil.extension, 21kB, 14/06

4:
MappeD\Sti\MinDataFil.extension, 21kB, 15/06


Læg mærke til at der kun er 4 grupper, mens der var 5 filer. Du behøver kun at tage en beslutning, dvs. vælge blandt en af disse 4 grupper, siden begge filer i gruppe #2, repræsenterer den samme. Hvis du kun endte op med en relation betyder at at alle dine filer er ens og der ikke er grund til nogen beslutning, du kan blot overføre hvilken som helst af filerne videre til din resultats-mappestruktur.

Hvordan finder du så gruppen af filerne der kan være ens? Du går bare gennem mappestrukturerne samtidig og noterer filer med samme navn. Filer der ikke findes i alle mappestrukturerne er enten blevet tilføjet eller fjernet så der er nødt til at blive taget en beslutning. Hvis du laver et GUI hvor man tager beslutningerne kan du måske antage at filerne er nye hvis de ikke findes i alle mappestrukturerne. Man kan så "beslutte" at fjerne dem hvis nødvendigt.

Hvad med omdøbninger? En løsning her kunne være at sortere alle filerne efter størrelse efter de er fundet. Hvis filer har samme størrelse kan du checke om de samme indhold. Men der er ikke nogen rigtig løsning her, for selv hvis de har samme størrelse kan det jo være meningen der skal være en kopi under andet navn.

En måde at håndtere stierne på kunne være en rekursiv datastruktur, hvis .NETs faciliteter ikke er tilstrækkelige eller der du vil understøtte flere platform kunne strukturen være noget i stil med:

Fold kodeboks ind/udCSharp kode 


Hvor hver mappestruktur er der sådan en rod-"Folder", som du så dykker ned i samtidigt. Hvis du har mapper A, B, C, og du går ned i A\MinMappe, gør du det samme for Folder-objektet for B og C.

Hvis du laver noget grafisk, kunne du eventuelt kigge efter om der findes nogle diff-biblioteker du kan integrere.




Indlæg senest redigeret d. 24.10.2014 13:53 af Bruger #14645
Hvis du vil vide hvilke filer der er ens, så kan du med fordel beregne en hashværdi for dem. Jeg lavede engang et program der kunne scanne mine harddiske efter dubletter (uanset filnavn, dato, osv - kun indhold), og så viste den en liste over dem. Ulempen her, er dog at du riskerer at to forskellige filer har den samme hashværdi.

Jeg smider koden ind her, så kan du evt. bruge det til noget inspiration.

Scanner.cs
Scanner alle filer i mappen og alle undermapper og gemmer resultatet i en database.
Fold kodeboks ind/udCSharp kode 


Modeller og Database
Brugte LINQtoSQL...
Fold kodeboks ind/udCSharp kode 


MainWindow.xaml.cs
Opdaterer GUI med mulige identiske filer
Fold kodeboks ind/udCSharp kode 


Håber du kan bruge det til noget..




Uden at komme med et konkret eksempel, ville jeg nok selv prøve at implementere IEqualityComparer interfacet.

http://msdn.microsoft.com/en-us/library/System.Collections.IEqualityComparer(v=vs.110).aspx



Hej Søren

Tak! Mange tak!
Se det var lige sådan nogle tanker jeg havde, for selve sammenligningen er ikke så svær. Det ligger mest i filer jeg selv skal sammenligne, så en visning af de to filer er nok - så kan jeg afspille begge film, sange, se begge billeder om de er ens og tage en beslutning.

Problemet for mig er at jeg nogle steder har ryddet lidt op, nogle steder har omstruktureret og andre steder ikke har.
Så strukturen er nærmere således:

C:\Phone backup\Phone Card\IMG\Tyson\213345.jpg 17/5/12 14kb
C:\Users\User\Backup_Space\Phone\Card\Min hund Tyson\213345.jpg 10/4/09 14kb
C:\Samsung_Organized\Images\Hund\Tyson\Lille\213345.jpg 01/01/14 14kb

Sådan er det over det hele med ALLE filer, så filerne flytter lokation og dato (efter hvornår jeg har taget backup igen), men filnavnene ændrer sig ikke. Derfor jeg skal tage stilling og vise begge to når jeg ser en forskel, så jeg kan tage en beslutning.

Regner med at jeg vil i den endelige mappe vil jeg samle alt struktur som der er fra alle lokationer uanset hvor rodet så bliver, for så er alt samlet et sted og kan flyttes rundt derefter.
Så den endelige struktur ville blive: C:\Complete organized\

Dermed ville mapperne blive:
C:\Complete organized\
C:\Complete organized\Phone backup\
C:\Complete organized\Phone backup\Phone Card\
C:\Complete organized\Phone backup\Phone Card\IMG\
C:\Complete organized\Phone backup\Phone Card\IMG\Tyson\
C:\Complete organized\Backup_Space\
C:\Complete organized\Backup_Space\Phone\
C:\Complete organized\Backup_Space\Phone\Card\
C:\Complete organized\Backup_Space\Phone\Card\Min hund Tyson\
C:\Complete organized\Images\
C:\Complete organized\Images\Hund\
C:\Complete organized\Images\Hund\Tyson\
C:\Complete organized\Images\Hund\Tyson\Lille\

Så som du kan se så skal jeg jo kunne definere for hver sti hvor deres "root" vil starte henne, og så skal den lave mapper for hver af dem i den endelige struktur. Tænkte så at hvis jeg nu sørgede for at lave destinationsmappen som en del af et website kunne jeg lave en lille side der kunne vise alle billeder i noget struktur så jeg kunne nemt se hvilke billeder der lå flere steder i mapper og derefter få overblik den vej igennem.

Problemet er så "blot" at strukturmæssigt er jeg lidt lost omkring hvordan jeg kan flytte en mappe ind i den nye struktur, så når næste mappe kommer skal den sammenlignes med filerne i den nye struktur og så se om der er forskelle.
Altså min objektmodel hvordan jeg nemmest kan opbygge den i C# så det bliver organiseret ordentligt, og hvordan jeg nemt kan se om der er forskelle i den endelige lokation og om der er forskel i filerne der ligges ind?
Hvordan foreslår i at jeg nemmest kan lave nogle objekter der kan håndtere dette?



Hvad med bare at hente dem ud i et Git repo og committe ændringerne?
Så har du historik og alt muligt.



Hvad med bare at hente dem ud i et Git repo og committe ændringerne?
Så har du historik og alt muligt.


Hvordan finder den ændringerne ved at du har 600 af de samme filer kopieret ud i 70 forskellige mapper?



Hvordan finder den ændringerne ved at du har 600 af de samme filer kopieret ud i 70 forskellige mapper?

Har man da det?

Jeg har lavet noget i den stil...jeg har mit repo, som bare er en tom mappe med 'git init'. Jeg har så en anden tom mappe, som jeg kopierer et projekt over i. Jeg løber så igennem alle filer i mit git repo (ingen til at starte med) og ser, om de findes i det andet dir. Hvis ikke, så laver jeg en 'git rm' på den, for så er den slettet siden sidst. Derefter kopierer jeg alle filerne over i mit git repo og kører 'git add' på dem. Til sidst laver jeg en 'git commit' og nu er første version så i mit repo.

Næste gang gør jeg det samme...henter filerne til et tomt dir, tjekker om alle filerne i mit git repo stadig findes i den nye kopi, og sletter dem, i repoet, hvis det ikke er tilfældet. Derefter kopierer alle filer over i repoet og git add'er dem. Til sidst 'git commit' og nu er den nye backup versioneret.

Og så fremdeles.



Hvordan finder den ændringerne ved at du har 600 af de samme filer kopieret ud i 70 forskellige mapper?

Har man da det?

Jeg har lavet noget i den stil...jeg har mit repo, som bare er en tom mappe med 'git init'. Jeg har så en anden tom mappe, som jeg kopierer et projekt over i. Jeg løber så igennem alle filer i mit git repo (ingen til at starte med) og ser, om de findes i det andet dir. Hvis ikke, så laver jeg en 'git rm' på den, for så er den slettet siden sidst. Derefter kopierer jeg alle filerne over i mit git repo og kører 'git add' på dem. Til sidst laver jeg en 'git commit' og nu er første version så i mit repo.

Næste gang gør jeg det samme...henter filerne til et tomt dir, tjekker om alle filerne i mit git repo stadig findes i den nye kopi, og sletter dem, i repoet, hvis det ikke er tilfældet. Derefter kopierer alle filer over i repoet og git add'er dem. Til sidst 'git commit' og nu er den nye backup versioneret.

Og så fremdeles.

Ja det er der, eftersom jeg spørg herinde til hjælp.
Det drejer sig om flere års backup hvor der oftest blot er en mappe med dato, som er en komplet kopi af både telefon og kort. Nogle mapper er struktureret 20%, andre er lavet til en anden struktur med 40% oprydning, andre er fra helt andre telefoner så den naturlige struktur er anderledes fordi Sony laver en anden struktur end Samsung, og HTC laver en helt tredje. Forskellige apps til håndtering af billeder er forskellige steder, og nogle telefoner har haft nogle forskellige apps til det og på den næste har jeg haft nogle andre apps.

Så tror jeg vil prøve Nicky's lidt af så jeg kan sikre mig at filerne er ens ud fra hashværdier. Det synes jeg virker ret fedt i forhold til hvad jeg skal løse.

----------------------------------------------------

Efter at have prøvet Nicky's kode af med Hash værdier af filer må jeg sige HOLD da op det er effektivt!
Laver en dictionary med hash-værdier, og i den anden er en liste af filer der har samme hash-værdi. Dermed kan jeg nemt se hvilke hash-værdier der har mere end en fil der peger på samme fil.
Altså dem der har en liste med over 1 fil til samme hashværdi er dem jeg skal vælge imellem, og "godkende", resten vil bare blive kopieret som de er fordi der kun er en fil.
Så mangler bare at lave en simpel sti opdaterer, så jeg får relative stier på fra og til med "~/Billeder/Biler/TFSI/Seat Leon...".
Så er det nemt at opbygge den nye struktur og kopiere over. PLUS denne vil jo være helt perfekt til når der fremover skal samles til samme bibliotek, for kan nu se hvilke filer der allerede ligger i destinationen og dermed ved at de ikke skal kopieres endnu engang. Den bliver bare endnu et direktory der skal tages med i sammenligningen.



Indlæg senest redigeret d. 04.11.2014 14:20 af Bruger #17215
t