Laden...

Duplikate - nur neuste Datei behalten

Erstellt von FullHouse vor 8 Jahren Letzter Beitrag vor 8 Jahren 3.064 Views
F
FullHouse Themenstarter:in
14 Beiträge seit 2014
vor 8 Jahren
Duplikate - nur neuste Datei behalten

Hallo,
ich habe folgendes Problem:
Ich suche mit C# Dateien mit dem gleichen Namen jedoch einer anderen Endung.
z.B: test.txt, test.pdf, test.psd, test.doc usw...

Manche Dateien sind mehrfach über verschiedene Ordner mehrfach vorhanden.
Die Suche habe ich bereitsbewerkstelligt...
Gebe ich als Input im Programm nun z.B. "123" bekomme ich:

D:\Dokumente\blabla\123.3
D:\Dokumente\UFW-C\123.1
D:\Dokumente\Sosos\soso\123.1

Nun möchte ich erst abfragen ob und welche Dateien doppelt borhanden sind.
Danach will ich die Datei die neuste Datei hersbekommen.

Aber ich weiß nicht wie ich das anstellen soll.

Zur Info: Schlussendlich sollen die neueren Dateien der Duplikate in einen definierten Ordner verschoben und die anderen gelöscht werden. (Hier weiß ich wie ich vorgehen muss)

Bitte um Hilfe!
MFg FullHouse

16.835 Beiträge seit 2008
vor 8 Jahren

Naja; Du musst noch definieren, wie die Kriterien sein sollen, nachdem Du die "neueste Version" herausfindest.
Ansonsten sehe ich ehrlich gesagt keine Frage in Deinem Post 😃 Was hast Du versucht? Was ist das exemplarische Ziel? Wo hängts?

F
FullHouse Themenstarter:in
14 Beiträge seit 2014
vor 8 Jahren

Achja sorry.
Die neuste Datei wäre in diesem Fall jene mit dem jüngsten Änderungsdatums.

J
251 Beiträge seit 2012
vor 8 Jahren

Schon die FileInfo-Klasse angeschaut?

6.911 Beiträge seit 2009
vor 8 Jahren

Hallo FullHouse,

hast du dir schon LinQ angeschaut? Damit lässt sich das komfortabel lösen.
Grob so:


IEnumerable<FileInfo> files = SearchForFiles("123");

var duplicateFiles = files
	.GroupBy(fi => fi.Name)
	.Where(grp => grp.Count() > 1);

foreach (var duplicate in duplicateFiles)
{
	var tmp = duplicate
		.OrderByDescending(fi => fi.LastWriteTimeUtc)
		.ToList();

	FileInfo fileToKeep = tmp[0];

	for (int i = 1; i < tmp.Count; ++i)
	{
		tmp[i].MoveTo(...);
	}
}

mfG Gü

Stellt fachliche Fragen bitte im Forum, damit von den Antworten alle profitieren. Daher beantworte ich solche Fragen nicht per PM.

"Alle sagten, das geht nicht! Dann kam einer, der wusste das nicht - und hat's gemacht!"

F
FullHouse Themenstarter:in
14 Beiträge seit 2014
vor 8 Jahren

Danke gfoidl...
Verstehe den Code leider nicht ganz ich weiß nicht wie ich den bei mir unterbringen soll:

       //Textdatei in Array schreiben
            string[] lines = System.IO.File.ReadAllLines(textfile);
            Console.WriteLine(lines[0]);
         
            // Suspend the screen.


            System.Console.ReadLine();

            string sDir = @"D:\Dokumente\";

           
            //Verzeichnisse im Hauptordner ermitteln
            foreach (string d in Directory.GetDirectories(sDir))
            {

                //Textdatei Zeile für Zeile durchgegen
                foreach (string i in lines)
                {

                        foreach (string f in Directory.GetFiles(d, i+".*"))
                        {

                            Console.WriteLine(Path.GetFileName(f));
                            Console.WriteLine(f);


                            }

                    }

                }
               

            }
6.911 Beiträge seit 2009
vor 8 Jahren

Hallo FullHouse,

was hat dieser Code mit der Fragestellung von oben zu tun?

Ich meins nicht böse, aber ich rate dir die Grundlagen anhand eines Buches, etc. zu erlernen und ganz einfache Beispiel-Projekte zu erstellen. Dann wirst du dieses Problem einfach lösen können.

mfG Gü

Stellt fachliche Fragen bitte im Forum, damit von den Antworten alle profitieren. Daher beantworte ich solche Fragen nicht per PM.

"Alle sagten, das geht nicht! Dann kam einer, der wusste das nicht - und hat's gemacht!"

F
FullHouse Themenstarter:in
14 Beiträge seit 2014
vor 8 Jahren

Ja tut mir Leid, hier konnte man nun wirklich keine Frage entnehmen.
Ich bin den Code nun durchgegangen und er ist mir klar.

Allerdings frage ich mich wieso du "files" als Variable deklariert hast...
Meine Datien bekomme ich per

Directory.GetFiles(d, i + ".*")

.

Wie hast du dir diese Zeile gedacht?

IEnumerable<FileInfo> files = SearchForFiles("123");

16.835 Beiträge seit 2008
vor 8 Jahren

Das ist ein Platzhalter, der alles sein kann.
Das ist nur Beispiel-Code, keine fertige Implementierung.... die kann man nie erwarten; dafür aber Eigeninitative.
Bitte lies Dir nochmal Punkt 1 und 4 in [Hinweis] Wie poste ich richtig? durch.

6.911 Beiträge seit 2009
vor 8 Jahren

Hallo FullHouse,

Wie hast du dir diese Zeile gedacht?

wegen

Gebe ich als Input im Programm nun z.B. "123" bekomme ich:

Allerdings frage ich mich wieso du "files" als Variable deklariert hast...

Irgendwoher muss eine Auflistung der Dateien herkommen. Im Beispiel hab ich das halt so beispielhaft (;-)) gelöst. Du kannst das natürlich auch anders lösen. Wichtiger ist das Verständnis des LinQ-Teils und der nachfolgenden Schleife. Der Rest ist eben nur rein beispielhaft.

mfG Gü

Stellt fachliche Fragen bitte im Forum, damit von den Antworten alle profitieren. Daher beantworte ich solche Fragen nicht per PM.

"Alle sagten, das geht nicht! Dann kam einer, der wusste das nicht - und hat's gemacht!"

F
FullHouse Themenstarter:in
14 Beiträge seit 2014
vor 8 Jahren

Das ich das dann selber einbringen muss ist mir klar...
Aber wenn ich richtig liege sollte in der files-Variable die Dateien liegen in denen ich überprüfen will ob sie Duplikate sind.

6.911 Beiträge seit 2009
vor 8 Jahren

Hallo FullHouse,

So ist es, daher auch die Deklaration von files:


IEnumerable<FileInfo> files

Und für meine beispielhafte Methode "SearchForFiles" baust du deine Methode zum Suchen und Finden der Dateien ein. Schau dir dazu auch [Snippet] Verzeichnisse und Dateien rekursiv durchlaufen an, das kann und wird dir helfen.

mfG Gü

Stellt fachliche Fragen bitte im Forum, damit von den Antworten alle profitieren. Daher beantworte ich solche Fragen nicht per PM.

"Alle sagten, das geht nicht! Dann kam einer, der wusste das nicht - und hat's gemacht!"

F
FullHouse Themenstarter:in
14 Beiträge seit 2014
vor 8 Jahren

Zum suchen und finden habe ich ja schon einen weg wie aus meinem Code zu lesen ist 😉

Habe nun

Directory.GetFiles(d, i + ".*")[0]; 

der Variable files zu geordnet.
Dann bekomme ich den Fehler, der string könne nicht impliziert werden.

16.835 Beiträge seit 2008
vor 8 Jahren

Dein Code ist aber - entgegen Deiner Textbeschreibung des Problems - nicht rekursiv.

F
FullHouse Themenstarter:in
14 Beiträge seit 2014
vor 8 Jahren

und wie der rekursiv ist...
Er sucht alle Unterordner von 😄\Dokumente ab

6.911 Beiträge seit 2009
vor 8 Jahren

Hallo FullHouse,

nein rekursiv ist er nicht. Siehe verlinktes Snippet wie es richtig geht.

Aber darüber brauchen wir hier nicht weiter zu diskutieren.

mfG Gü

Stellt fachliche Fragen bitte im Forum, damit von den Antworten alle profitieren. Daher beantworte ich solche Fragen nicht per PM.

"Alle sagten, das geht nicht! Dann kam einer, der wusste das nicht - und hat's gemacht!"

F
FullHouse Themenstarter:in
14 Beiträge seit 2014
vor 8 Jahren

Okay er sucht allerdings alle meine Unterordner ab und somit bin ich zufrieden:
Die Ausgabe sieht nämlich aus wie ich im ersten Post geschrieben habe:
D:\Dokumente\blabla\123.3
D:\Dokumente\UFW-C\123.1
D:\Dokumente\Sosos\soso\123.1

Diese Werte stehen also im folgendem Array:

 Directory.GetFiles(d, i + ".*")

Nun möchte ich diese Werte der Variable files zuordnen doch ich bekomme immer diesen Fehler

463 Beiträge seit 2009
vor 8 Jahren

und wie der rekursiv ist...
Er sucht alle Unterordner von 😄\Dokumente ab

Meiner Meinung nach hast du leider nicht verstanden was rekursiv bedeutet... Bitte nimm den Tipp mit einem guten Buch an...

VG Stefan

F
FullHouse Themenstarter:in
14 Beiträge seit 2014
vor 8 Jahren

Hallo Leute,
ja ich werde mich mit einem Grundlagen Buch eindecken...

Ich habe gfoidls Vorschlag nun so verwendet:

      string sDir = @"D:\Dokumente\";
            //Verzeichnisse im Hauptordner ermitteln

            //Textdatei Zeile für Zeile durchgegen
            foreach (string i in lines)
            {



                List<FileInfo> files = Search_Files(sDir, i);

                var duplicateFiles = files
                    .GroupBy(fi => fi.Name)
                    .Where(grp => grp.Count() > 1);

                foreach (var duplicate in duplicateFiles)
                {
                    var tmp = duplicate
                        .OrderByDescending(fi => fi.LastWriteTimeUtc)
                        .ToList();

                    FileInfo fileToKeep = tmp[0];

                    for (int s = 1; s < tmp.Count; ++s)
                    {
                        tmp[s].MoveTo(@"D:\Dokumente\test.yx");
                    }
                }

            }


        }

Und ich habe auch verstanden, dass meine Funktion nicht rekursiv war...
Habe die verlinkte verwendet und zwar so:


public List<FileInfo> Search_Files(String strDir, String textzeile)
        {
            List<FileInfo> list = new List<FileInfo>();
            try
            {

                // 1. Für alle Dateien im aktuellen Verzeichnis
                foreach (String strFile in Directory.GetFiles(strDir, textzeile + ".*"))
                {
                    list.Add(new FileInfo(strFile));


                }
                foreach (String strSubDir in Directory.GetDirectories(strDir))
                { 
                    Search_Files(strSubDir, textzeile);
                }


            }
            catch (Exception)
            {
                // 3. Statt Console.WriteLine hier die gewünschte Aktion
                Console.WriteLine("error: " + strDir);
            }

            return (list);
        }

Das Ganze lässt sich so auch builden, allerdings funktioniert es noch nicht.
Für mich ist so alles logisch?

Kann mir jemand einen Tipp geben?

6.911 Beiträge seit 2009
vor 8 Jahren

Hallo FullHouse,

wenn für dich nun alles logisch ist, so ist das super, aber auch Zeit den nächsten Schritt zu gehen: [Artikel] Debugger: Wie verwende ich den von Visual Studio?
Damit kannst du sehen und prüfen was dein Programm macht und entsprechend den Code korrigieren. Das hilft dir viel mehr, als wenn wir dir hier den möglichen Fehler nennen.

mfG Gü

Stellt fachliche Fragen bitte im Forum, damit von den Antworten alle profitieren. Daher beantworte ich solche Fragen nicht per PM.

"Alle sagten, das geht nicht! Dann kam einer, der wusste das nicht - und hat's gemacht!"

F
FullHouse Themenstarter:in
14 Beiträge seit 2014
vor 8 Jahren

Habe mich nun auch im Debuggen versucht.
Nun habe ich wahrscheinlich den Fehler entdeckt.

Der return Befehl, der Methode gibt zwar die Liste zurück, allerdings nur mit einem, dem ersten Wert.

Habe im Internet nach einer Lösung gesucht, es scheint allerdings das nicht viele dieses Problem fragen.

Und nun ist es glaube ich das erste Mal angebracht euch um Hilfe zu bitten.

4.939 Beiträge seit 2008
vor 8 Jahren

Tipp: was machst du mit dem Rückgabewert beim Aufruf der rekursiven Methode?

T
314 Beiträge seit 2013
vor 8 Jahren

Dann hast Du doch das Problem schon gefunden. Nun musst Du doch nur noch schauen, warum nur ein Wert drinnen ist.

Hinweis:
Wie und wo werden denn Einträge der Liste hinzugefügt?

F
FullHouse Themenstarter:in
14 Beiträge seit 2014
vor 8 Jahren

Naja, eben in foreach-Schleife welche die dateien ausgibt...
Das merkwürdige ist nur, dass wenn ich die Liste noch in der Methode anzeigen lasse, bekomme ich alle Werte...

4.939 Beiträge seit 2008
vor 8 Jahren

Hast du meinen Tipp gelesen und verstanden?


List<FileInfo> sublist = Search_Files(strSubDir, textzeile);

Jetzt mußt du nur noch überlegen, wie du die Einträge der 'sublist' in die lokale 'list' einträgst.