Kennt einer für Unix/Linux nen Tool was zwei Dateibäume vergleicht, so dass ich synchronisieren kann, also doppelte Dateien in verschiedenen Pfaden erkennt und mir sagt, welche Dateien nur im einen Baum vorhanden sind?
Doppelte Datei finden in Ordner/Platte etc.
-
-
Zitat von gandro
Kennt einer für Unix/Linux nen Tool was zwei Dateibäume vergleicht, so dass ich synchronisieren kann, also doppelte Dateien in verschiedenen Pfaden erkennt und mir sagt, welche Dateien nur im einen Baum vorhanden sind?
Und die Bäume waren ursprünglich mal von der Verzeichnisstruktur her synchron (du suchst also eine Funktionalität wie ein vereinfachtes, bidirektionales rsync(1)) oder ist ihre Relation zueinander wie Kraut und Rüben, sodass man sich nicht auf Dateinamen, Dateigrößen oder Modifikationszeiten verlassen kann? Im ersteren Fall könnte es genügen, sich aus find(1)(, sort(1)) und comm(1) (gemeinsame oder unikale Zeilen zweier sortierter Dateien ausgeben) fix ein Skript zusammenzukleben, das nur mit den unterschiedlichen Zeilen operiert.EDIT: Das sähe wohl etwa so aus (hab ich gerade in Notepad++ zusammengebaut, kann nicht für die Funktionalität garantieren):
Code
Alles anzeigenpushd $TREE1 find | sed 's/^\.\///' | sort > /tmp/tree1 popd; pushd $TREE2 find | sed 's/^\.\///' | sort > /tmp/tree2 popd # in TREE2 fehlende Dateien kopieren comm -23 /tmp/tree1 /tmp/tree2 | \ while read f; do f=${f#./} # schneller als dirname [ -d $TREE2/${f%/*} ] || mkdir -p $TREE2/${f%/*} [ -e $TREE2/$f ] || cp $TREE1/$f $TREE2/$f done # dasselbe andersrum comm -13 /tmp/tree1 /tmp/tree2 | \ while read f; do f=${f#./} [ -d $TREE1/${f%/*} ] || mkdir -p $TREE1/${f%/*} [ -e $TREE1/$f ] || cp $TREE2/$f $TREE1/$f done rm /tmp/tree1 /tmp/tree2
Auch wenn ich auf einmal dir gar nicht sagen kann, was dieser Schnippsel besser als
erledigen soll.
-
Zitat von DosAmp
Und die Bäume waren ursprünglich mal von der Verzeichnisstruktur her synchron (du suchst also eine Funktionalität wie ein vereinfachtes, bidirektionales rsync(1)) oder ist ihre Relation zueinander wie Kraut und Rüben, sodass man sich nicht auf Dateinamen, Dateigrößen oder Modifikationszeiten verlassen kann? Im ersteren Fall könnte es genügen, sich aus find(1)(, sort(1)) und comm(1) (gemeinsame oder unikale Zeilen zweier sortierter Dateien ausgeben) fix ein Skript zusammenzukleben, das nur mit den unterschiedlichen Zeilen operiert.EDIT: Das sähe wohl etwa so aus (hab ich gerade in Notepad++ zusammengebaut, kann nicht für die Funktionalität garantieren):
Hm.. werds mir am Abend dann noch mal anschauen, wenn ich Zeit habe. comm(1) hab ich bisher aber nicht in Betracht gezogen - frage mich wie gut das mit Binärdateien auskommt, weil geht in erster Linie um Binärdateien.Aber ich glaube (angeschaut hab ichs wie gesagt noch nicht genauer) dein Programm hat das gleiche Problem wie rsync (was aber sowieso nur unidirektional ist) oder csync oder unison (beide bidirektional, tun was dein rsync-Zweizeiler tut in einer Zeile) auch:
Sie erkennen gleiche Dateien mit unterschiedlichen Pfaden nicht. Und das will ich schon, sonst hätt ich längst rsync genommen. Hab mir gestern Abend nen Mockup erstellt, wie ich mir die Ausgabe von so nem Programm überhaupt vorstelle (syncen soll das ja vorerst nichtmals, weil die Platten ggf. 100km Luftlinie dazwischen haben):
Code
Alles anzeigen# gleiche Datei, unterschiedlicher Pfad [b]/a/Filme/Kinofilme/Pulp.Fiction.avi === /b/pulp.fiction.avi[/b] # Ordner fehlt in Baum /b [b]/a/Musik/Amity in Fame/ --- <missing>[/b] # Datei fehlt in Baum /a [b]<missing> +++ /b/Musik/Tchaikovsky.mp3[/b] # Unterschiedliche Datei in beiden Bäumen [b]/a/notes.txt !!! /b/notes.txt[/b] # gleiche, in beiden Pfaden vorhandene Dateien werden [b][u]nicht[/u][/b] angezeigt. # ...
Die Anzeige dass der nen kompletten Ordner als fehlend erkennt ist nur optional, im Zweifelsfall soll der nur auf Dateiebene arbeiten.
-
gleiche dateien in unterschiedlichen pfaden?
hm meine erste idee wäre jetzt von allen files ne prüfsumme erstellen lassen und dann schauen, welche prüfsumme (und die datei dazu) nur in einem davon existiert
hab ich was übersehen, oder ist das das, was du suchst? -
Zitat von oreissig
gleiche dateien in unterschiedlichen pfaden?
hm meine erste idee wäre jetzt von allen files ne prüfsumme erstellen lassen und dann schauen, welche prüfsumme (und die datei dazu) nur in einem davon existiert
hab ich was übersehen, oder ist das das, was du suchst?mein kleines bashscript mit sqlite funktioniert auf diese weise
ist nur leider nicht wirklich optimiert, aber der PROOF OF CONCEPT geht
ich überleg ob ich nich daraus ne eigene suchfunktion bastel ohne checksumme, weil dieses ganzen desktop indexierungkram funktioniert nicht wirklich so wie ich will -
Zitat von oreissig
gleiche dateien in unterschiedlichen pfaden?
hm meine erste idee wäre jetzt von allen files ne prüfsumme erstellen lassen und dann schauen, welche prüfsumme (und die datei dazu) nur in einem davon existiert
hab ich was übersehen, oder ist das das, was du suchst?
Das hast du schon richtig erkannt - wenn ich mir dafür aber nen Script mache, will ich das direkt in richtig, mit "Datenbank", so dass ich bei nem späteren Vergleich nur für neue Dateien nochmals Prüfsumme berechnen muss. -
wenn du das mit SQLite machst, könnteste vermutlich auch gleich die Auswertung in die DB verlegen und müsstest nur noch ne kleine output-routine selber proggen
-
Ich hatte mal nen Script in Python angefangen, weil das mit Sets die ganze Vergleichlogik direkt in der Sprache hat. Das Updaten und Speichern des Dateibaums ist die grössere Frage.
An sich stellt sich die Frage ob man ne gewöhnliche Tabelle macht (aka. SQLite oder son Krams) oder mit nem Binärbaum arbeitet (was für die Abfrage ob ein Hash bereits existiert schnell wie Pommes ist, für Abfrage ob Dateipfad schon existiert hingegen weniger).
Nachtrag: Generell ist das Updaten der DB die meisten Gedanken wert, man muss sich überlegen ob man den Dateibaum durchgeht und für jede Datei in der DB nachfragt, oder ob man direkt die DB durchscrollt und überprüft ob sich an der Datei was geändert hat - dann hat man aber das Problem, dass neue Dateien explizit gesucht werden müssen.
-
die datenbank wird die tabelle ja wohl auch kaum als verkettete liste abspeichern
-
da gandro sowas ja momentan sucht, und es schon vorschläge gibt
mach ich maln extra thread draus:so sieht momentan meine (auf die schnelle gemachte) methode aus:
datenbank erstellen:
sqlite test1.db "create table liste ( name text, hash text, size int)"checkeuda.sh [Pfad] [Datenbankname]
sqleuda.sh [Datenbank] [Datei]
Bash#!/bin/bash HASH=$(md5sum $1| awk '{print $1}') NAME=$1 SIZE=$(stat -c %s $1) echo $NAME, $SIZE, $HASH sqlite $2 "insert into liste (name, hash, size) values ( \"$NAME\", \"$HASH\", \"$SIZE\")"
um die doppelte dateien anzuzeigen (geordnet nach hash) + befehl in xargs (wenn man möchte ):
doppeltdatei.sh [datenbank]Bash#!/bin/bash #$1 datenbankname sqlite $1 select * from liste INNER JOIN (select *, count(hash) as anzahl from liste group by hash having ( count(hash) > 1)) group by liste.hash;" # select liste.name from liste INNER JOIN (select *, count(hash) as anzahl from liste group by hash having ( count(hash) > 1)) group by liste.hash;" | xargs -i file {}
checkeuda.sh /home/ test1.db
und dann doppeltdatei.sh test1.db
funktioniert bei mir
kann man sicherlich noch verbessern, da es in bash nich gerade das schnellste ist, ausserdem müsste es kein problem sein zwei datenbanken zu vergleichen wenn man den den sqlbefehl etwas verändert (wäre eigentlich sinnvoller ne neue tabelle zu erstellen statt datenbank) -
Nett, aber an sich nicht was ich gesucht habe, möchte ja zwei Datenbanken vergleichen, nicht eine innerhalb sich selber.
Bin bei meinem eigenen Entwurf aber auch nicht weiter. Bin am überlegen ob ich Dateisystem durchlaufen soll und das in neue DB schreiben (sonst bleiben gelöschte Dateien erhalten), oder ob ich die DB durchlaufen soll, dann ist die Frage aber wie ich neue Dateien hinzufüge.
-
zwei zu vergleichen is kein problem
muss nur dad doppeltedatei abfragescript veraendern werden
machste nen kreuzprodukt und dann zaehlste welcher hash mehr als 1x vorkommt und joinst das mit den kreuzprodukt -
-
geht bestimmt auch besser
aber heutzutage ist das selbst mit 100.000 datensätze garnich mal son problem -
Was verstehst du unter Kreuzprodukt bei SQL? Kenn' bisher erst die Grundsytax von SQL, frage daher einfach mal Blöd.
Im überigen, Crosszitat ausm UIT:
Zitat von oreissig
die datenbank wird die tabelle ja wohl auch kaum als verkettete liste abspeichern
SQLite speichert Tabellen intern durchaus als Binärbaum. Dooferweise aber nur mit nem 64bit-Key, wo SHA1 türlich nicht reinpasst. Andererseits, wenn ich den Hash als INTEGER PRIMARY KEY nehme, dann hab ich Probleme mit doppelten Dateien in der gleichen Tabelle. Irgendwie doof.Problem für mich ist auch, dass ich gerne eine Datei pro Datenbaum habe. Aber so wie es ausschaut kann SQLite nur jeweils mit einer Datenbankdatei mit mehreren Tabellen arbeiten, und nicht mit zwei Datenbankdateien.K, geht doch. -
Ich pushe das hier mal, weil bin mir echt nicht sicher wie ich das aktuelle Problem lösen soll.
Ausgangslage: Es existiere eine befüllte Tabelle, mit den Spalten filename, size, mtime, sha1sum. Nun wird der Dateibaum durchgegangen, und für jede Datei überprüft ob sich size oder mtime im Dateisystem verändert haben, falls ja, wird die sha1-Summe neu berechnet (erst nach dem SELECT mtime, size FROM tabelle WHERE filename=$dateiname Query also) und zusammen mit den neuen size und mtime-Werten in die Tabelle geschrieben.
Frage ist nun, was ist mit sqlite3 effizienter:
1. Alle überprüften Zeilen irgendwie zu markieren und am Ende alle nicht-überprüften Zeilen zu löschen, weil die dazugehörigen Dateien offenbar gelöscht wurden.
2. Alle überprüften Zeilen in eine neue Tabelle schreiben, und am Ende die alte Tabelle löschen.
-
kommt vll auch drauf an, wieviel änderungen du jeweils durchführst. beim löschen muss er die tupel wohl erst nochmal finden, weswegen bei der ersten variante die performance wohl mit der anzahl der veränderungen abnimmt, während die 2. variante allein durch die anzahl der dateien skaliert.
EDIT: und letztere ist natürlich größer
-
Kann man bei SQL(ite) JOINs/SELECTs als neue Tabellen speichern?
Hatte heute Mittag noch folgende Idee: Die ID aller betrachteten Dateien wird in eine Tabelle im RAM geschrieben, am Ende wird ein JOIN oder so gemacht, und das dann gespeichert.
Nachtrag: SQL-92 kennt SELECT INTO. SQLite kennt INSERT INTO bzw CREATE TABLE AS SELECT. Müsste damit gehen.
Jetzt mitmachen!
Du hast noch kein Benutzerkonto auf unserer Seite? Registriere dich kostenlos und nimm an unserer Community teil!