Hallo Leute, ich suche ein Programm, um Verzeichnisinhalte (incl. Unterverzeichnisse) abzugleichen. Bezüglich des Abgleichs habe ich einen Spezialwunsch: Neue und geänderte Dateien sollen in ein drittes Verzeichnis kopiert werden (z. B. um davon eine CD zu brennen oder das ganze per Diskette auf einen anderen Rechner zu kopieren). Also nach dem Motto: vergleiche die Verzeichnisse ~/dir1 mit ~/dir2 und schreibe neue/geänderte Dateien nach ~/changes Gibt es da irgendwas passendes? Gruß Christian Boltz -- Registrierter Linux-Nutzer #239431 Linux - life is too short for reboots.
Am Donnerstag, 10. Januar 2002 23:13 schrieb Christian Boltz:
Hallo Leute,
ich suche ein Programm, um Verzeichnisinhalte (incl. Unterverzeichnisse) abzugleichen.
Bezüglich des Abgleichs habe ich einen Spezialwunsch:
Neue und geänderte Dateien sollen in ein drittes Verzeichnis kopiert werden (z. B. um davon eine CD zu brennen oder das ganze per Diskette auf einen anderen Rechner zu kopieren).
Also nach dem Motto: vergleiche die Verzeichnisse ~/dir1 mit ~/dir2 und schreibe neue/geänderte Dateien nach ~/changes
Gibt es da irgendwas passendes?
Hallo Christian Wie wärs denn mit CVS. Da kannst Du gleichzeitig noch alle Änderungen loggen und Diffs zwischen sämtlichen Bearbeitungen einer Datei machen. CU Thorsten -- Thorsten Körner || info@thorstenkoerner.de Dannenkoppel 51 || thorstenkoerner@thorsti.org 22391 Hamburg || GNU-GPG Key: 2D2C4868C007C4FA http://www.123tk.de || reg. Linux-User:#187283
Hallo Thorsten, hallo Leute, Am Freitag, 11. Januar 2002 00:26 schrieb Thorsten Körner:
Am Donnerstag, 10. Januar 2002 23:13 schrieb Christian Boltz:
ich suche ein Programm, um Verzeichnisinhalte (incl. Unterverzeichnisse) abzugleichen.
Bezüglich des Abgleichs habe ich einen Spezialwunsch: Also nach dem Motto: vergleiche die Verzeichnisse ~/dir1 mit ~/dir2 und schreibe neue/geänderte Dateien nach ~/changes
Wie wärs denn mit CVS. Da kannst Du gleichzeitig noch alle Änderungen loggen und Diffs zwischen sämtlichen Bearbeitungen einer Datei machen.
Ich wollte eigentlich nicht mit Kanonen auf Spatzen schießen ;-) Ein CVS wäre wohl etwas überdimensioniert... Gibt es nicht einfach so etwas wie "diff für Verzeichnisse"? Gruß Christian Boltz -- Registrierter Linux-Nutzer #239431 Linux - life is too short for reboots.
Am Sonntag, 13. Januar 2002 18:15 schrieb Christian Boltz:
Hallo Thorsten, hallo Leute,
Am Freitag, 11. Januar 2002 00:26 schrieb Thorsten Körner:
Am Donnerstag, 10. Januar 2002 23:13 schrieb Christian Boltz:
ich suche ein Programm, um Verzeichnisinhalte (incl. Unterverzeichnisse) abzugleichen.
Bezüglich des Abgleichs habe ich einen Spezialwunsch: Also nach dem Motto: vergleiche die Verzeichnisse ~/dir1 mit ~/dir2 und schreibe neue/geänderte Dateien nach ~/changes
Wie wärs denn mit CVS. Da kannst Du gleichzeitig noch alle Änderungen loggen und Diffs zwischen sämtlichen Bearbeitungen einer Datei machen.
Ich wollte eigentlich nicht mit Kanonen auf Spatzen schießen ;-) Ein CVS wäre wohl etwas überdimensioniert...
Gibt es nicht einfach so etwas wie "diff für Verzeichnisse"?
Hallo Christian So ein Overload ist CVS, glaube ich auch nicht. Mit Cervisia, hast Du alle gewünschten Infos in Einem "Diff & Co." . Ich empfehle Dir das auch vor dem Hintergrund, dass mit KDE3 auch die Möglichkeit kommt CVS direkt mit dem Konqueror zu verwalten. Dort gibt es dann ein KPart und wenn Du mit dem Konqui in ein CVS-Verzeichnis wechselst, dann wird das Cervisia-Plugin aufgerufen. Alle Veränderungen an Dateien etc hast Du dann automatisch im Blick. Also wenn es um mehr, als nur zwei, drei Files geht, dann würd' ich es mir ruhig mal anschauen. CU Thorsten -- Thorsten Körner || info@thorstenkoerner.de Dannenkoppel 51 || thorstenkoerner@thorsti.org 22391 Hamburg || GNU-GPG Key: 2D2C4868C007C4FA http://www.123tk.de || reg. Linux-User:#187283
* Christian Boltz schrieb am 13.Jan.2002:
Gibt es nicht einfach so etwas wie "diff für Verzeichnisse"?
diff -r Bernd -- ACK = ACKnowledge = Zustimmung | NAC = No ACknowledge = keine Zustimmung DAU = Dümmster Anzunehmender User | LOL = Laughing Out Loud = Lautes Lachen IIRC = If I Remember Correctly = Falls ich mich richtig erinnere OT = Off Topic = Am Thema (der Liste) vorbei |Zufallssignatur 11
Hallo Bernd, hallo Thorsten, hallo Jürgen, hallo Waldemar, hallo Leute, vielen Dank für die umfangreichen Antworten! Ich habe mich erstmal für diff -r -q entschieden, da es IMHO am einfachsten per Script zu verwenden ist. Außerdem werde ich so gezwungen, endlich mal die man bash zu lesen ;-) Am Sonntag, 13. Januar 2002 19:58 schrieb Bernd Brodesser:
* Christian Boltz schrieb am 13.Jan.2002:
Gibt es nicht einfach so etwas wie "diff für Verzeichnisse"?
diff -r
Das hatte ich doch glatt übersehen, dass diff auch mit Verzeichnissen geht ;-) Ich habe noch ein -q angehängt, da es mich nicht interessiert, was sich geändert hat, ich möchte nur neue/gelöschte/geänderte Dateien aufgelistet haben. Jetzt muss ich mir nur noch ein Script basteln, das die geänderten Dateien in ein drittes Verzeichnis kopiert. (Nur aus Verzeichnis A, in Verzeichnis B wird _nichts_ verändert) Hier also der Zwischenstand: $ diff -r -q verz_a/ verz_b/ Files verz_a/changedfile and verz_b/changedfile differ Only in verz_a/: new_in_a Only in verz_b/: new_in_b Für das Schreiben des Scripts bin ich jetzt aber zu müde ;-) Grundgedanke ist der folgende: diff-Ausgabe in eine Datei umleiten [1], diese mit while und read $1 $2 $3 $4 $5 zeilenweise einlesen, dann - falls $1 = "Files" -> Datei geändert -> $2 [2] ins Changed-Verzeichnis - falls $1 = "Only" und $3 = "verz_a" -> neue Datei -> $4 ins Changed-Verz. - falls $1 = "Only" und $3 = "verz_b" -> gelöschte Datei -> Hinweis ausgeben Ach ja, evtl. muss ich vor dem Kopieren noch Unterverzeichnisse anlegen. Wie ich das anstelle, überlege ich mir morgen (also in ca. 10 Minuten ;-) Gruß Christian Boltz [1] sollte auch mit einer Pipe gehen, oder? [2] "verz_a/" muss ich natürlich aus $2 herauslöschen lassen. TEST=`echo "verz_a" | cut -c 7-` sollte das erledigen. -- Registrierter Linux-Nutzer #239431 Linux - life is too short for reboots.
* Christian Boltz schrieb am 15.Jan.2002:
Am Sonntag, 13. Januar 2002 19:58 schrieb Bernd Brodesser:
* Christian Boltz schrieb am 13.Jan.2002:
Gibt es nicht einfach so etwas wie "diff für Verzeichnisse"?
diff -r
Das hatte ich doch glatt übersehen, dass diff auch mit Verzeichnissen geht ;-)
Ich habe noch ein -q angehängt, da es mich nicht interessiert, was sich geändert hat, ich möchte nur neue/gelöschte/geänderte Dateien aufgelistet haben.
Jetzt muss ich mir nur noch ein Script basteln, das die geänderten Dateien in ein drittes Verzeichnis kopiert. (Nur aus Verzeichnis A, in Verzeichnis B wird _nichts_ verändert)
diff bietet noch einge Möglichkeiten, vielleicht kanst Du es mit diff alleine machen. Ich kenne die aber auch nicht. Hast Du Dir schon mal info diff angesehen? Da gibt es noch mehr als unter man diff. Kleiner Tipp: info ist grauselig, aber wenn Du KDE und somit den konqueror hast, so geb in der Eingabezeile einfach info:/diff ein und Du bekommst ein halbwegs vernünftiges info. Falls Du kein konqueror hast, so würde ich pinfo nehmen, weiß jetzt aber nicht, ob pinfo bei SuSE dabei ist. Bernd -- Hast Du bei Problemen schon in der SuSE-Support-Datenbank (SDB) nachgesehen? Auf Deinem Rechner: http://localhost/doc/sdb/de/html/index.html | mit Apache: http://localhost/doc/sdb/de/html/key_form.html | Zufalls- Tagesaktuell bei SuSE: http://sdb.suse.de/sdb/de/html/index.html | signatur 2
Hallo Christian, * Am 15.01.2002 um 23:56 Uhr schrieb Christian Boltz:
Hallo Bernd, hallo Thorsten, hallo Jürgen, hallo Waldemar, hallo Leute,
vielen Dank für die umfangreichen Antworten!
;-)
Hier also der Zwischenstand: $ diff -r -q verz_a/ verz_b/ Files verz_a/changedfile and verz_b/changedfile differ Only in verz_a/: new_in_a Only in verz_b/: new_in_b
Für das Schreiben des Scripts bin ich jetzt aber zu müde ;-)
Grundgedanke ist der folgende: diff-Ausgabe in eine Datei umleiten [1], diese mit while und read $1 $2 $3 $4 $5 zeilenweise einlesen, dann - falls $1 = "Files" -> Datei geändert -> $2 [2] ins Changed-Verzeichnis - falls $1 = "Only" und $3 = "verz_a" -> neue Datei -> $4 ins Changed-Verz. - falls $1 = "Only" und $3 = "verz_b" -> gelöschte Datei -> Hinweis ausgeben
[1] sollte auch mit einer Pipe gehen, oder? [2] "verz_a/" muss ich natürlich aus $2 herauslöschen lassen. TEST=`echo "verz_a" | cut -c 7-` sollte das erledigen.
zu [1] diff -r -q verz_a/ verz_b/ | while read Zeile; do set -- $Zeile echo "$1 # $2 # $3 # $4 # $5" # nur als Beispiel done zu [2] Zeile="verz_a/bla/blub.txt" # zu zerlegende Zeile echo ${Zeile:7} # schreibt alles ab der 8 Stelle # 0-7 wird übersprungen bzw. echo ${Zeile#verz_a/} # entfernt 'verz_a/' aus der Zeile hiermit spart man sich den Aufruf des externen <cut> ;-) Jürgen -- Die letzten Worte eines Turmspringers: "Ach, ist das Wasser heute schön klaaaaaaaaaaaar!" / Registered Linux-User #130804 http://counter.li.org \ \ Linux Stammtisch Bremerhaven http://linux.hs-bremerhaven.de /
Hallo Jürgen, hallo Bernd, hallo Leute, Am Mittwoch, 16. Januar 2002 08:22 schrieb Juergen Schwarting:
* Am 15.01.2002 um 23:56 Uhr schrieb Christian Boltz:
Hier also der Zwischenstand: $ diff -r -q verz_a/ verz_b/ Files verz_a/changedfile and verz_b/changedfile differ Only in verz_a/: new_in_a Only in verz_b/: new_in_b
Für das Schreiben des Scripts bin ich jetzt aber zu müde ;-)
heute schon wieder zu müde ;-) Naja, wofür gibt es ein Wochenende?
Grundgedanke ist der folgende: diff-Ausgabe in eine Datei umleiten [1], diese mit while und read $1 $2 $3 $4 $5 zeilenweise einlesen, dann - falls $1 = "Files" -> Datei geändert -> $2 [2] ins Changed-Verzeichnis - falls $1 = "Only" und $3 = "verz_a" -> neue Datei -> $4 ins Changed-Verz. - falls $1 = "Only" und $3 = "verz_b" -> gelöschte Datei -> Hinweis ausgeben
[1] sollte auch mit einer Pipe gehen, oder? [2] "verz_a/" muss ich natürlich aus $2 herauslöschen lassen. TEST=`echo "verz_a" | cut -c 7-` sollte das erledigen.
zu [1]
diff -r -q verz_a/ verz_b/ | while read Zeile; do set -- $Zeile echo "$1 # $2 # $3 # $4 # $5" # nur als Beispiel
Die letzten 2 Zeilen habe ich zwar noch nicht ganz verstanden, aber sie scheinen zu funktionieren ;-) Jetzt muss ich nur noch (per if oder case) die Ausgabe von diff auswerten.
done
zu [2]
Zeile="verz_a/bla/blub.txt" # zu zerlegende Zeile
echo ${Zeile:7} # schreibt alles ab der 8 Stelle # 0-7 wird übersprungen bzw.
echo ${Zeile#verz_a/} # entfernt 'verz_a/' aus der Zeile
hiermit spart man sich den Aufruf des externen <cut> ;-)
netter Trick ;-) Danke für die Tips! So langsam wird es wohl Zeit für einen Ausdruck der man bash... Gruß Christian Boltz -- Registrierter Linux-Nutzer #239431 Linux - life is too short for reboots.
On Wed, 16 Jan 2002, Christian Boltz wrote:
Am Mittwoch, 16. Januar 2002 08:22 schrieb Juergen Schwarting:
* Am 15.01.2002 um 23:56 Uhr schrieb Christian Boltz: [..]
Grundgedanke ist der folgende: diff-Ausgabe in eine Datei umleiten [1], diese mit while und read $1 $2 $3 $4 $5 zeilenweise einlesen, dann - falls $1 = "Files" -> Datei geändert -> $2 [2] ins Changed-Verzeichnis - falls $1 = "Only" und $3 = "verz_a" -> neue Datei -> $4 ins Changed-Verz. - falls $1 = "Only" und $3 = "verz_b" -> gelöschte Datei -> Hinweis ausgeben
[1] sollte auch mit einer Pipe gehen, oder? [2] "verz_a/" muss ich natürlich aus $2 herauslöschen lassen. TEST=`echo "verz_a" | cut -c 7-` sollte das erledigen.
zu [1]
diff -r -q verz_a/ verz_b/ | while read Zeile; do set -- $Zeile echo "$1 # $2 # $3 # $4 # $5" # nur als Beispiel
$ cd /tmp/test $ mkdir "test verz" $ mkdir verz_b (beide ein bisschen gefuellt) $ diff -rq diff -rq test\ verz/ verz_b/ [..] Only in verz_b/: configure Files test verz/configure.in and verz_b/configure.in differ Only in test verz/: configure.in~ [..] $ diff -rq test\ verz/ verz_b/ | while read zeile; do set -- $zeile; echo "$1 # $2 # $3 # $4 # $5"; done [..] Only # in # verz_b/: # configure # Files # test # verz/configure.in # and # verz_b/configure.in Only # in # test # verz/: # configure.in~ [..]
Die letzten 2 Zeilen habe ich zwar noch nicht ganz verstanden, aber sie scheinen zu funktionieren ;-)
s.o. Nur ohne Leerzeichen (und andere Sonderzeichen). Die erste Variablen $1 bis ... beinhalten die Kommandozeilenargumente. Mit "set --" koennen diese "neu befuellt" werden. Ein 1=x geht nicht. Zu while read zeile -> siehe "help read" aus man bash, "read variable" liest die Standardeingabe zeilenweise und packt die jew. zeile in die variable. Das echo sollte klar sein. Halbwegs robust ist IMO folgendes, mit dem ich gestern angefangen habe, ist aber noch sehr unvollstaendig und ich hatte dich auch flasch verstanden, was du wo haben willst, bietet aber hoffentlich ein paar Ideen, wie du die jew. Zeilen auswerten kannst. Achso, ist glaube ich weniger performant, aber dafuer glaube ich recht portabel... ==== dirdiff.sh ==== #! /bin/bash DIFF="/usr/bin/diff" GREP="/usr/bin/grep" SED="/usr/bin/sed" CP="echo /bin/cp -i" ## erstmal mit echo entschaerft RM="echo /bin/rm -i" ## erstmal mit echo entschaerft usage="Usage: `basename $0` Verz_eins Verz_zwei" if test "x$#" != "x2"; then echo "$usage"; exit 1; fi dir_OLD="$1" dir_NEW="$2" test -d "$dir_OLD" && test -d "$dir_NEW" || exit 1 function parse() { while read "line"; do if echo "$line" | $GREP -q '^Files.*differ$'; then ## Achtung: das ist "anfaellig gegen Dateinamen wie z.B.: ## 'XXX and YYY' und 'Files XXX' und 'XXX differ' etc. ## die naechste Zeile sollte letztere beiden Probleme loesen, ## aber Datei-/Verzeichnisnamen mit ' and ' sind wohl kaum ## automatisch aufzuloesen... Das folgende grep sollte diese ## Faelle aber erkennen koennen. if echo "$line" | $GREP -q ' and .* and '; then echo "Uhoh, filename conflict!" >&2 echo "$line" >&2 else line=`echo "$line" | $SED 's¡^Files ¡¡;s¡differ$¡¡'` oldfile=`echo "$line" | $SED 's¡Files \(.*\) and .*¡\1¡'` newfile=`echo "$line" | $SED 's¡Files .* and \(.*\) differ$¡\1¡'` echo "'$oldfile' <-> '$newfile'" ## mach was mit den unterschiedlichen Dateien... z.B. ein ## diff -u $oldfile $newfile > "$andersdir.$oldfile.diff" ## oder sowas in der Art... fi else if echo "$line" | $GREP -q '^Only' then dir=`echo "$line" | $SED 's¡Only in \([^:]*\):.*¡\1¡'` file=`echo "$line" | $SED 's¡Only in .*: \(.*\)$¡\1¡'` case "$dir" in $dir_OLD*) $CP "${dir}/${file}" "${dir_NEW}/${file}" ;; $dir_NEW*) $RM "${dir_NEW}/${file}" ;; *) echo "Uhoh, whot's this?" >&2 exit 1 ;; esac fi fi done } $DIFF -rq "$dir_OLD" "$dir_NEW" | parse ==== EOF ====
echo ${Zeile#verz_a/} # entfernt 'verz_a/' aus der Zeile
hiermit spart man sich den Aufruf des externen <cut> ;-)
netter Trick ;-) Danke für die Tips!
Siehe man bash, Abschnitt "Brace Expansion"...
So langsam wird es wohl Zeit für einen Ausdruck der man bash...
*hehe* -dnh -- Lusers. Can't live with 'em, can't run 'em over in the car park and make it look like an accident... -- Chris King
Ups. War wohl doch schon zu muede... ;( On Thu, 17 Jan 2002, David Haller wrote:
Die erste Variablen $1 bis ... beinhalten die Kommandozeilenargumente.
s/erste//
while read "line"; do if echo "$line" | $GREP -q '^Files.*differ$'; then ## Achtung: das ist "anfaellig gegen Dateinamen wie z.B.: ## 'XXX and YYY' und 'Files XXX' und 'XXX differ' etc. ## die naechste Zeile sollte letztere beiden Probleme loesen, ^^^^^^^^ ich hab anschliessend nochmal umgestellt, gemeint ist die erste Zeile nach dem else:
else line=`echo "$line" | $SED 's¡^Files ¡¡;s¡differ$¡¡'` oldfile=`echo "$line" | $SED 's¡Files \(.*\) and .*¡\1¡'` newfile=`echo "$line" | $SED 's¡Files .* and \(.*\) differ$¡\1¡'`
^^^^^ ^^^^^^ und das ist natuerlich Schwachfug, nachdem ich die oben erst entfernt habe... Muss also heissen: oldfile=`echo "$line" | $SED 's¡^\(.*\) and .*¡\1¡'` newfile=`echo "$line" | $SED 's¡.*and \(.*\)$¡\1¡'` Sorry fuer die Fehler... -dnh, hui, danke sigmonster, die sig passt mal wieder :) -- "Awooga! Awooga! Someone put my clothes back on!"
Hallo Bernd, hallo David, hallo Leute, vielen Dank für die Erklärung und die Anregungen. Ich habe vorhin noch ein wenig am Script gebastelt (bevor ich meine heutigen Mails abgerufen habe). Bisher wird allerdings nur ausgegeben, ob eine Datei verändert, gelöscht oder neu erstellt wurde, es fehlt also noch mkdir und cp ;-) Hier also mein Zwischenstand: ---------- diffdirs.sh ---------- # Aufruf: # diffdirs $verz_alt $verz_neu $verz_fuer_diffs # (derzeit noch hardcoded fuer Testzwecke) verz_alt=/tmp/verz_a verz_neu=/tmp/verz_b verz_diffs=/tmp/verz_diffs # mögliche Ausgaben von diff: # Only in /tmp/verz_a/: test # Files /tmp/verz_a/test3 and /tmp/verz_b/test3 differ # Only in /tmp/verz_a/verz_a1: muster # falls $1 = "Files" -> Datei geändert -> $2 [2] ins Changed-Verzeichnis # falls $1 = "Only" und $3 = "verz_neu" -> neue Datei -> $4 ins Changed-Verz. # falls $1 = "Only" und $3 = "verz_alt" -> gelöschte Datei -> Hinweis ausgeben ##### Verzeichnisinhalt vergleichen... diff -r -q $verz_alt/ $verz_neu/ | while read Zeile; do set -- $Zeile ##### Datei geändert oder nur in einem Verzeichnis? case "$1" in Files) # geänderte Datei echo "geänderte Datei: " ${2#$verz_alt/};; Only) # Datei nur in einem Verzeichnis ##### Datei nur in $verz_alt vorhanden, also gelöscht -> Hinweistext if [ ${3:0:${#verz_alt}} == $verz_alt ] ; then echo -n "Datei gelöscht: " ; SUBDIR=${3:${#verz_alt}+1}; SUBDIR=${SUBDIR:0:${#SUBDIR}-1}; if [ -n "${SUBDIR}" ]; then echo -n $SUBDIR/ ; fi echo $4 ##### Datei nur in $verz_neu vorhanden, also neu -> nach $verz_diffs kopieren ##### vorläufig nur Hinweistext elif [ ${3:0:${#verz_neu}}==$verz_neu ]; then echo -n "neue Datei: " ; SUBDIR=${3:${#verz_alt}+1}; SUBDIR=${SUBDIR:0:${#SUBDIR}-1}; if [ -n "${SUBDIR}" ]; then echo -n $SUBDIR/ ; fi echo $4 ##### sonstiges (sollte nicht vorkommen) else echo "Unbekannte Diff-Ausgabe :-( (if-Block)" fi ##### wichtig: letzte Zeile vor "esac" muss mit zwei ; enden! Hier also ##### ein Dummy (wird geändert, sobald das Script wirklich fertig ist ;-) test -n a==b;; *) echo "Unbekannte Diff-Ausgabe :-( (case-Block)";; esac; done; exit 0; ---------- diffdirs.sh ---------- Wie man sieht, hat man bash doch geholfen, auch wenn es nicht gerade eine leichte Lektüre ist ;-) Das Einbauen der cp-Befehle und das Anlegen der Verzeichnisse dürfte kein Problem darstellen. Am Donnerstag, 17. Januar 2002 02:27 schrieb David Haller:
Halbwegs robust ist IMO folgendes, mit dem ich gestern angefangen habe, ist aber noch sehr unvollstaendig und ich hatte dich auch flasch verstanden, was du wo haben willst, bietet aber hoffentlich ein paar Ideen, wie du die jew. Zeilen auswerten kannst.
Das auf jeden Fall ;-)
Achso, ist glaube ich weniger performant, aber dafuer glaube ich recht portabel...
==== dirdiff.sh ==== [interessantes Script] ## Achtung: das ist "anfaellig gegen Dateinamen wie z.B.: ## 'XXX and YYY' und 'Files XXX' und 'XXX differ' etc. ## die naechste Zeile sollte letztere beiden Probleme loesen, ## aber Datei-/Verzeichnisnamen mit ' and ' sind wohl kaum ## automatisch aufzuloesen... Das folgende grep sollte diese ## Faelle aber erkennen koennen.
Dort, wo ich dieses Script einsetze, wird mit "normalen" Dateinamen gearbeitet ;-) Es handelt sich z. T. um Dateien, die später mal auf einen Webserver hochgeladen werden, da machen sich Sonderzeichen, Leerzeichen, Umlaute und sonstiger Unfug nicht so gut ;-)
[Rest des interessanten Scripts]
Nochmal herzlichen Dank für Eure Hilfe und die Tips! Gruß Christian *Nachteule* Boltz -- Registrierter Linux-Nutzer #239431 Linux - life is too short for reboots.
Hallo Leute, heute mal nur ein kleineres Problem, das mir beim Schreiben des Scripts zum Verzeichnisvergleich Schwierigkeiten macht. diff liefert u. a. die folgende Ausgabezeile: Files /tmp/verz_a/test3 and /tmp/verz_b/test3 differ Meine Frage ist nun die folgende: Wie trenne ich das Verzeichnis vom Dateinamen ab? Dazu müsste man die Position des letzten / in einer Variable ermitteln und diese dann in Pfad und Dateiname trennen. Ich stelle mir das ganze so vor: $ALLES=/tmp/verz_a/testfile [irgendwelche Bash[1]-Kommandos - nur: welche?] Das Ergebnis soll so aussehen: echo $NUR_PFAD /tmp/verz_a/ echo $NUR_DATEI testfile Gruß Christian Boltz [1] auch andere Lösungen sind OK, aber ich würde die bash bevorzugen ;-) -- Registrierter Linux-Nutzer #239431 Linux - life is too short for reboots.
* Christian Boltz schrieb am 19.Jan.2002:
Ich stelle mir das ganze so vor:
$ALLES=/tmp/verz_a/testfile
[irgendwelche Bash[1]-Kommandos - nur: welche?]
Das Ergebnis soll so aussehen:
echo $NUR_PFAD /tmp/verz_a/
dirname
echo $NUR_DATEI testfile
basename man dirname man basename Bernd -- Umsteiger von Microsoft Windows xx? Hast Du schon file://usr/doc/howto/de/DE-DOS-nach-Linux-HOWTO.txt gelesen? Auch file://usr/doc/Books/Linuxhandbuch.dvi ist zu empfehlen. |Zufallssignatur 1
On Sat, 19 Jan 2002, Christian Boltz wrote:
heute mal nur ein kleineres Problem, das mir beim Schreiben des Scripts zum Verzeichnisvergleich Schwierigkeiten macht.
diff liefert u. a. die folgende Ausgabezeile: Files /tmp/verz_a/test3 and /tmp/verz_b/test3 differ
Meine Frage ist nun die folgende: Wie trenne ich das Verzeichnis vom Dateinamen ab? Dazu müsste man die Position des letzten / in einer Variable ermitteln und diese dann in Pfad und Dateiname trennen.
Ich stelle mir das ganze so vor:
$ALLES=/tmp/verz_a/testfile
[irgendwelche Bash[1]-Kommandos - nur: welche?]
man basename, man dirname Oder bash-intern: DATEI="/tmp/verz_a/test3" DIRNAME="${DATEI%\/*}" BASENAME="${DATEI##*\/}" Aber du hast dir dazu den Kommentar in meinem script durchgelesen, gell? -dnh -- The only truly safe "embedded system" is the system that has an axe embedded in it... -- Tanuki
Hallo David, hallo Bernd, hallo Leute, Am Sonntag, 20. Januar 2002 00:19 schrieb David Haller:
On Sat, 19 Jan 2002, Christian Boltz wrote:
heute mal nur ein kleineres Problem, das mir beim Schreiben des Scripts zum Verzeichnisvergleich Schwierigkeiten macht.
diff liefert u. a. die folgende Ausgabezeile: Files /tmp/verz_a/test3 and /tmp/verz_b/test3 differ
Meine Frage ist nun die folgende: Wie trenne ich das Verzeichnis vom Dateinamen ab? Dazu müsste man die Position des letzten / in einer Variable ermitteln und diese dann in Pfad und Dateiname trennen.
DATEI="/tmp/verz_a/test3" DIRNAME="${DATEI%\/*}" BASENAME="${DATEI##*\/}"
Aber du hast dir dazu den Kommentar in meinem script durchgelesen, gell?
Ja, aber betrachte Dir mal die Uhrzeit meiner lezten Mails ;-) Ich hatte auch schon mit % und ## experimentiert. Mein Fehler war wohl, dass ich den \ vor dem / vergessen hatte und dass ich keinen * mit angegeben habe... So, dann werde ich wohl das Script fertigschreiben. Ich poste es dann in den nächsten Tagen, da vielleicht noch mehr Leute Interesse daran haben. Nochmal Danke an Dich und an Bernd für die Hilfe. Gruß Christian Boltz -- Registrierter Linux-Nutzer #239431 Linux - life is too short for reboots.
On Mon, 21 Jan 2002, Christian Boltz wrote:
Am Sonntag, 20. Januar 2002 00:19 schrieb David Haller:
DIRNAME="${DATEI%\/*}" BASENAME="${DATEI##*\/}"
Aber du hast dir dazu den Kommentar in meinem script durchgelesen, gell?
Ja, aber betrachte Dir mal die Uhrzeit meiner lezten Mails ;-)
Ich bezog mich auf meine erste Mail in diesem Thread von '17.01.02 02:27:21' samt Korrektur in '17.01.02 04:51:00'. Deine naechste war dann von '17.01.02 23:48:42', sollte dann doch gereicht haben ;)
Ich hatte auch schon mit % und ## experimentiert. Mein Fehler war wohl, dass ich den \ vor dem / vergessen hatte und dass ich keinen * mit angegeben habe...
So, dann werde ich wohl das Script fertigschreiben. Ich poste es dann in den nächsten Tagen, da vielleicht noch mehr Leute Interesse daran haben.
Mach dich auf Korrekturen gefasst ;) -dnh -- The things you have to do to have kids are fine, and I'll take as much of that as I can get, but the actual kids themselves?" -- Matt McLeod
Hallo David, hallo Leute, Am Montag, 21. Januar 2002 22:23 schrieb David Haller:
On Mon, 21 Jan 2002, Christian Boltz wrote:
Am Sonntag, 20. Januar 2002 00:19 schrieb David Haller:
DIRNAME="${DATEI%\/*}" BASENAME="${DATEI##*\/}"
Aber du hast dir dazu den Kommentar in meinem script durchgelesen, gell?
Ja, aber betrachte Dir mal die Uhrzeit meiner lezten Mails ;-)
Ich bezog mich auf meine erste Mail in diesem Thread von '17.01.02 02:27:21' samt Korrektur in '17.01.02 04:51:00'. Deine naechste war dann von '17.01.02 23:48:42', sollte dann doch gereicht haben ;)
Das Problem war nicht der Abstand zwischen den Mails, sondern die Uhrzeit an sich ;-) Da Du auch ein "Nachtarbeiter" bist, kennst Du wohl die damit verbundenen Probleme, oder? <gähn>
So, dann werde ich wohl das Script fertigschreiben. Ich poste es dann in den nächsten Tagen, da vielleicht noch mehr Leute Interesse daran haben.
Das waren jetzt ein paar paar ;-) Tage, ich hatte inzwischen einfach zuviel zu tun. Aber: Was lange währt, wird endlich gut (hoffe ich zumindest...)
Mach dich auf Korrekturen gefasst ;)
Ich bitte darum ;-) Kurz zum Aufruf: $1 -> verz_alt: Verzeichnis mit altem Stand $2 -> verz_neu: Verzeichnis mit Änderungen $3 -> verz_fuer_diffs: hierhin werden geänderte Dateien kopiert Dateien, die in verz_alt und verz_neu existieren und geändert wurden, werden nach verz_fuer_diffs kopiert, ebenso Dateien, die nur in verz_neu existieren. Dateien, die nur in verz_alt vorhanden sind, führen dazu, dass die Meldung "Datei gelöscht: xxx" ausgegeben wird. Statt einer Datei kann es sich jeweils auch um ein Verzeichnis handeln. ----------------------------------------------------------- #! /bin/bash # (c) Christian Boltz <ChristianBoltz@web.de> # Dieses Script unterliegt den Bedingungen der GPL. usage="Usage: `basename $0` Verzeichnis_alt Verzeichnis_neu Verzeichnis_fuer_diffs Verzeichnis_alt: Ausgangsverzeichnis Verzeichnis_neu: geändertes Verzeichnis Verzeichnis_fuer_diffs: Verzeichnis, in dem geänderte Dateien abgelegt werden sollen" if test "x$#" != "x3"; then echo "$usage"; exit 1; fi VERZ_ALT="$1" VERZ_NEU="$2" VERZ_DIFFS="$3" # CP="echo -> cp" CP="cp" # MKDIR="echo -> mkdir -p" MKDIR="mkdir -p" ################### VERZEICHNISINHALT VERGLEICHEN ############## diff -r -q $VERZ_ALT/ $VERZ_NEU/ | while read Zeile; do set -- $Zeile case "$1" in ##### DATEI GEÄNDERT ##### Files) SUBDIR="${2%\/*}" if [ -n "${SUBDIR}" ]; then SUBDIR=${SUBDIR}/ ; fi; SUBDIR=${SUBDIR#$VERZ_ALT/} FILENAME="${2##*\/}" if [ ! -d ${VERZ_DIFFS}/${SUBDIR} ]; then # bei Bedarf Verzeichnis anlegen $MKDIR ${VERZ_DIFFS}/${SUBDIR} ; fi; $CP $2 $VERZ_DIFFS/$SUBDIR$FILENAME ;; ##### DATEI NUR IN EINEM VERZEICHNIS ##### Only) ##### DATEI NUR IN $VERZ_ALT -> GELÖSCHT-> HINWEISTEXT ##### if [ ${3:0:${#VERZ_ALT}} == $VERZ_ALT ] ; then echo -n "*** Datei gelöscht: "; SUBDIR=${3:${#VERZ_ALT}+1}; SUBDIR=${SUBDIR:0:${#SUBDIR}-1}; if [ -n "${SUBDIR}" ]; then echo -n $SUBDIR/; fi echo $4 ##### DATEI NUR IN $VERZ_NEU -> NACH $VERZ_DIFFS KOPIEREN ##### elif [ ${3:0:${#VERZ_NEU}}==$VERZ_NEU ]; then SUBDIR=${3:${#VERZ_ALT}+1}; SUBDIR=${SUBDIR:0:${#SUBDIR}-1}; if [ -n "${SUBDIR}" ]; then SUBDIR=${SUBDIR}/ ; fi; if [ ! -d ${VERZ_DIFFS}/${SUBDIR} ]; then # bei Bedarf Verzeichnis anlegen $MKDIR ${VERZ_DIFFS}/${SUBDIR} ; fi; $CP -R $VERZ_NEU/${SUBDIR}${4} $VERZ_DIFFS/${SUBDIR}${4} ; # Only in ... kann auch Verzeichnisse liefern, deshalb -R ##### sonstiges (sollte nicht vorkommen) else echo "Unbekannte Diff-Ausgabe :-( (if-Block)" >&2; echo $1 $2 $3 $4 $5 exit 1; fi ;; ##### sonstiges (sollte nicht vorkommen) *) echo "Unbekannte Diff-Ausgabe :-( (case-Block)" >&2; echo $1 $2 $3 $4 $5 exit 1 ;; esac; done; exit 0; ----------------------------------------------------------- Ach ja: Ich habe die Überprüfung der Dateinamen bewusst vermieden. Falls jemand z. B. Dateinamen mit Leerzeichen verwendet, wird er wohl eine Fehlermeldung ernten - aber das zu Recht, was haben schließlich Leerzeichen im Dateinamen zu suchen? Wer es absichern möchte: "set -- $Zeile" entsprechend anpassen bwz. austauschen, eine recht gute Lösung hat ja David schon in diesem Tread gepostet. Für meine Zwecke ist das allerdings nicht nötig, ich verwende ordentliche Dateinamen ;-) Gruß Christian Boltz -- Registrierter Linux-Nutzer #239431 Linux is like a wigwam: no gates, no windows, but an apache inside.
Hallo Leute, Am Montag, 4. Februar 2002 20:54 schrieb Christian Boltz:
[ Script, um 2 Verzeichnisse zu vergleichen und geänderte Dateien in ein drittes Verzeichnis zu kopieren ]
Am Montag, 21. Januar 2002 22:23 schrieb David Haller:
Mach dich auf Korrekturen gefasst ;)
Ich bitte darum ;-)
Alles muss man selbst machen ;-) Inzwischen habe ich das Script ausführlich getestet und noch ein paar Fehler gefunden. Ich stelle die aktuelle Version von diffdirs online unter http://tux.boltz.de.vu
Kurz zum Aufruf: $1 -> verz_alt: Verzeichnis mit altem Stand $2 -> verz_neu: Verzeichnis mit Änderungen $3 -> verz_fuer_diffs: hierhin werden geänderte Dateien kopiert [genaueres in meiner Mail vom 4. Februar]
Gruß Christian Boltz -- Registrierter Linux-Nutzer #239431 Linux - life is too short for reboots.
* Christian Boltz schrieb am 16.Jan.2002:
Am Mittwoch, 16. Januar 2002 08:22 schrieb Juergen Schwarting:
set -- $Zeile echo "$1 # $2 # $3 # $4 # $5" # nur als Beispiel
Die letzten 2 Zeilen habe ich zwar noch nicht ganz verstanden, aber sie scheinen zu funktionieren ;-)
Hat set ein Argument, so werden die Argumente zu den Positionsparameter. Es so als hättest Du das Skript mit $Zeile als Argument aufgerufen. Das -- dient lediglich dazu, daß ein Parameter in $Zeile, der mit einem - anfängt nicht als Option für set interpretiert wird. Außerdem verhindert es, daß set seine Außgabe macht, die es macht, wenn es ohne Parameter aufgerufen wird, falls $Zeile leer ist. Mit dem echo weden die Positionsparameter $1 bis $5 ausgegeben mit je einem # dazwichen. Insgesamt wird $Zeile ausgegeben, mit jeweils ein # zwichen den einzelnen Wörter. Maximal aber nur 5 Wörter.
Jetzt muss ich nur noch (per if oder case) die Ausgabe von diff auswerten.
done
zu [2]
Zeile="verz_a/bla/blub.txt" # zu zerlegende Zeile
echo ${Zeile:7} # schreibt alles ab der 8 Stelle # 0-7 wird übersprungen bzw.
echo ${Zeile#verz_a/} # entfernt 'verz_a/' aus der Zeile
hiermit spart man sich den Aufruf des externen <cut> ;-)
netter Trick ;-)
Nö, nur bash angewandt. Bernd -- Welches Buch ist zu empfehlen? Schon mal bei SuSE vorbeigesehen? http://www.suse.de/de/products/books/index.html oder die Empfehlungen der SuSE-Entwickler auf dem eigenen Rechner? file:///usr/share/doc/sdb/de/html/literatur.html |Zufallssignatur 5
Hallo Christian, * Am 10.01.2002 um 23:13 Uhr schrieb Christian Boltz:
ich suche ein Programm, um Verzeichnisinhalte (incl. Unterverzeichnisse) abzugleichen.
Bezüglich des Abgleichs habe ich einen Spezialwunsch:
Neue und geänderte Dateien sollen in ein drittes Verzeichnis kopiert werden (z. B. um davon eine CD zu brennen oder das ganze per Diskette auf einen anderen Rechner zu kopieren).
Also nach dem Motto: vergleiche die Verzeichnisse ~/dir1 mit ~/dir2 und schreibe neue/geänderte Dateien nach ~/changes
Gibt es da irgendwas passendes?
keine Ahnung, aber hier ein kleines Script, dass diese Aufgabe erledigen sollte: ---[ schnipp ]--- #!/bin/bash ALTDIR=~/dir1 # Altes Verzeichnis NEUDIR=~/dir2 # Neues Verzeichnis CHANGEDIR=~/changes # Hierher werden Änderungen kopiert TMP=/tmp # Wo befinden sich die temp. Dateien TMP1=$TMP/index1 # Index für das Altverzeichnis TMP2=$TMP/index2 # Index für das Neuverzeichnis TMP3=$TMP/index3 # Index aller eindeutigen Verzeichnisse # ggf. Index1 löschen if [ -e "$TMP1" ]; then rm $TMP1 fi # Index des Altverzeichnis aufbauen find $ALTDIR -type f | while read Zeile; do CheckSum=$(md5sum -b "$Zeile") echo "A $CheckSum" done >>$TMP1 # ggf. Index2 löschen if [ -e "$TMP2" ]; then rm $TMP2 fi # Index des Neuverzeichnis aufbauen find $NEUDIR -type f | while read Zeile; do CheckSum=$(md5sum -b "$Zeile") echo "N $CheckSum" done >>$TMP2 # Index mit eindeutigen Dateien aufbauen cat $TMP1 $TMP2 | sort +1 -32 | uniq -u -s 1 -w 32 >$TMP3 # Alle eindeutigen Kandidaten etwas genauer unter die Lupe nehmen ;-) while read Zeile; do Satzart=$(echo "${Zeile:0:1}") # Satzart ermitteln if [ "$Satzart" == "N" ]; then # Nur Neuzugänge/Änderungen verarbeiten Datei=$(echo ${Zeile#*\*}) # Zugriffspfad extrahieren cp --parents "$Datei" $CHANGEDIR/ # Datei ins Change-Verzeichnis kopieren fi done <$TMP3 # Temp. Dateien löschen rm $TMP1 $TMP2 $TMP3 ---[ schnapp ]--- Das Ausschmücken und die Fehlerbehandlung überlasse ich Dir ;-) Da hier mit Hilfe von Checksummen gearbeitet wird, interessieren die Dateinamen und Zugriffszeiten nicht. Nur der reine Datei- inhalt wird verglichen. Das hat allerdings zur Folge, dass Dateien mit dem selben Inhalt aber unterschiedlichen Namen als identisch anerkannt und nicht kopiert werden. Hier ist vielleicht noch ein wenig Nacharbeit erforderlich. Jürgen -- Hast Du Zweifel, lass es ueberzeugend klingen. / Registered Linux-User #130804 http://counter.li.org \ \ Linux Stammtisch Bremerhaven http://linux.hs-bremerhaven.de /
Hallo Christian,
From the keyboard of Christian,
Hallo Leute,
ich suche ein Programm, um Verzeichnisinhalte (incl. Unterverzeichnisse) abzugleichen.
Bezüglich des Abgleichs habe ich einen Spezialwunsch:
Neue und geänderte Dateien sollen in ein drittes Verzeichnis kopiert werden (z. B. um davon eine CD zu brennen oder das ganze per Diskette auf einen anderen Rechner zu kopieren).
Also nach dem Motto: vergleiche die Verzeichnisse ~/dir1 mit ~/dir2 und schreibe neue/geänderte Dateien nach ~/changes
Gibt es da irgendwas passendes?
Vielleicht ist rsync oder unison was für dich. http://rsync.samba.org http://www.cis.upenn.edu/~bcpierce/unison/ bye Waldemar -- Are your questions smart enough? http://www.tuxedo.org/~esr/faqs/smart-questions.html
participants (6)
-
B.Brodesser@t-online.de
-
Christian Boltz
-
David Haller
-
Juergen Schwarting
-
Thorsten Körner
-
Waldemar Brodkorb