Linux Diff Tools: Liste der geänderten Dateien erstellen


14

Wie erstelle ich programmgesteuert mit Linux-Befehlszeilentools eine Liste der geänderten Dateien? Der Unterschied in einer bestimmten Datei (Delta, Patch) interessiert mich nicht. Ich möchte nur eine Liste neuer oder geänderter Dateien im Vergleich zur vorherigen Produktversion haben. Damit ich ein neues Produktupdate veröffentlichen kann.

Update: diff -qrErzeugt keine sehr praktische Ausgabe. Die Ausgabe von muss diff -qrebenfalls verarbeitet werden. Gibt es einen besseren Weg?


Was ist ein Beispiel für eine "bequeme" Ausgabe?
Frogstarr78

Antworten:


8

Ich habe dafür einen einfachen Ansatz: Benutze den rsync-Preview-Modus:

rsync -aHSvn --delete old_dir/ new-dir/

Die Dateien, die von diesem Befehl als "zu löschen" angezeigt werden, sind die "neuen" Dateien. Die anderen, die übertragen werden sollen, haben sich in gewisser Weise geändert. Weitere Informationen finden Sie auf der rsync-man-Seite.


13

Sie können das Diff- Tool verwenden: Siehe die Optionen -q und -r

-q  --brief
Output only whether files differ.

-r  --recursive
Recursively compare any subdirectories found.

Beispiel:

diff -qr dir1 dir2

Absolut schreckliche und unleserliche Ausgabe, überfüllt mit unsinnigen Informationen, Only indie auch dann angezeigt werden, wenn die Verzeichnisse ideale Kopien sind. Ich musste Änderungen mit einer alten Revision vergleichen und am Ende die gesamte Revision in ein separates Verzeichnis herunterladen und Standard-SVN-Tools zum Vergleichen verwenden. Dies scheint der einzige Weg zu sein…
Hi-Angel,

3

Das diffutilsPaket enthält ein lsdiffWerkzeug. diff -uÜbergeben Sie einfach die Ausgabe von an lsdiff:

diff -u --other-diff-options path1 path2 | lsdiff

Guter Vorschlag, danke. War im patchutilsPaket für mich (CentOS 5.x).
Steve Kehlet

Ja, Patchutils-Paket auch für Ubuntu / Debian.
Artfulrobot

1

Ich würde bei jedem Update einfach eine Datei anfassen, und dann können Sie Dateien finden, die seitdem mit geändert wurden find /tree/location -newer /last/update/file -print


1

Um nur den Namen der Dateien zu übernehmen, die sie geändert haben, verwende ich diesen Befehl:

diff -r dirt1 dir2 --brief | sed 's/^Only in \([^:]*\): /\1\//' | sed 's/^Files \(.*\) and .* differ/\1/'

Wenn Sie einige Dateien als Objektdateien oder Bibliotheksdateien ausschließen müssen, können Sie Folgendes verwenden:

diff -r dirt1 dir2 --brief --exclude "*.o" --exclude "*.a" | sed 's/^Only in \([^:]*\): /\1\//' | sed 's/^Files \(.*\) and .* differ/\1/'

1

Um eine Liste mit neuen oder geänderten Dateien programmgesteuert zu erstellen, ist die beste Lösung, die ich finden könnte, die Verwendung von rsync , sort und uniq :

(rsync -rcn --out-format="%n" old/ new/ && rsync -rcn --out-format="%n" new/ old/) | sort | uniq

Lassen Sie mich anhand dieses Beispiels erklären: Wir möchten zwei DokuWiki-Versionen vergleichen, um festzustellen, welche Dateien geändert und welche neu erstellt wurden.

Wir holen die Teere mit wget und extrahieren sie in die Verzeichnisse old/und new/:

wget http://download.dokuwiki.org/src/dokuwiki/dokuwiki-2014-09-29d.tgz
wget http://download.dokuwiki.org/src/dokuwiki/dokuwiki-2014-09-29.tgz
mkdir old && tar xzf dokuwiki-2014-09-29.tgz -C old --strip-components=1
mkdir new && tar xzf dokuwiki-2014-09-29d.tgz -C new --strip-components=1

Wenn Sie rsync auf eine Weise ausführen, werden möglicherweise neu erstellte Dateien übersehen, wie der Vergleich von rsync und diff hier zeigt:

rsync -rcn --out-format="%n" old/ new/

ergibt folgende Ausgabe:

VERSION
doku.php
conf/mime.conf
inc/auth.php
inc/lang/no/lang.php
lib/plugins/acl/remote.php
lib/plugins/authplain/auth.php
lib/plugins/usermanager/admin.php

Wenn Sie rsync nur in einer Richtung ausführen, werden die neu erstellten Dateien übersehen, und in der anderen Richtung werden gelöschte Dateien übersehen. Vergleichen Sie die Ausgabe von diff:

diff -qr old/ new/

ergibt folgende Ausgabe:

Files old/VERSION and new/VERSION differ
Files old/conf/mime.conf and new/conf/mime.conf differ
Only in new/data/pages: playground
Files old/doku.php and new/doku.php differ
Files old/inc/auth.php and new/inc/auth.php differ
Files old/inc/lang/no/lang.php and new/inc/lang/no/lang.php differ
Files old/lib/plugins/acl/remote.php and new/lib/plugins/acl/remote.php differ
Files old/lib/plugins/authplain/auth.php and new/lib/plugins/authplain/auth.php differ
Files old/lib/plugins/usermanager/admin.php and new/lib/plugins/usermanager/admin.php differ

Wenn Sie rsync in beide Richtungen ausführen und die Ausgabe sortieren, um Duplikate zu entfernen, wurde festgestellt, dass das Verzeichnis data/pages/playground/und die Datei data/pages/playground/playground.txtursprünglich übersehen wurden:

(rsync -rcn --out-format="%n" old/ new/ && rsync -rcn --out-format="%n" new/ old/) | sort | uniq

ergibt folgende Ausgabe:

VERSION
conf/mime.conf
data/pages/playground/
data/pages/playground/playground.txt
doku.php
inc/auth.php
inc/lang/no/lang.php
lib/plugins/acl/remote.php
lib/plugins/authplain/auth.php
lib/plugins/usermanager/admin.php

rsync wird mit diesen Argumenten ausgeführt:

  • -r in Verzeichnisse "rekursieren",
  • -c um auch Dateien mit identischer Größe zu vergleichen und nur "Überspringen basierend auf Prüfsumme, nicht Mod-Zeit & Größe",
  • -n "Probelauf ohne Änderungen durchführen" und
  • --out-format="%n" "Aktualisierungen mit dem angegebenen FORMAT ausgeben", hier "% n" nur für den Dateinamen

Die Ausgabe (Dateiliste) rsyncin beiden Richtungen wird kombiniert und sortiert sort, und diese sortierte Liste wird dann verdichtet, indem alle Duplikate mit entfernt werdenuniq


0

Sie sollten das gewünschte Ergebnis erhalten mit:

diff -r --brief dir1/ dir2/

0

Dies könnte den Trick machen:

compare_dirs()
{
    # Shows which files and directories exist in one directory but not both
    if [ $# -ne 2 ]
    then
        echo "Usage: compare_dirs dir1 dir2" >&2
        return 2
    fi
    for path
    do
        if [ ! -d "$path" ]
        then
            echo "Not a directory: $path" >&2
            return 1
        fi
    done
    comm -3 \
        <(cd -- "$1" && find . -printf '%P\0' | sort -z | quote_shell) \
        <(cd -- "$2" && find . -printf '%P\0' | sort -z | quote_shell)
}

0

Normalerweise legen Sie die Dateien in eine Art Versionskontrollsystem wie SubVersion oder git, da diese dies für Sie sofort erledigen können.

Sie können jedoch ein schnelles Skript mit einer for-Schleife für dir1 erstellen und dann jede Datei mit der in dir2 vergleichen. Die for-Schleife kann den Exit-Code von diff überprüfen, um festzustellen, ob die Dateien unterschiedlich waren.

Vielleicht so etwas:

for f in `(cd dir1 ; find .)`
do 
  diff $f ../dir2/$f
  if [ "$?" == "0" ]
  then 
    echo same
  else 
    echo diff: $f
  fi
done

Hinweis: Das Skript wurde nicht getestet, daher ist das obige Beispiel "bash inspired pseudocode" ...


Lass uns noch einen Versuch machen, aber mit Schwachkopf

Erstellen Sie einige Beispieldateien zum Spielen

mkdir -p dir1/test1/test11
mkdir -p dir1/test1/test12
mkdir -p dir1/test1/test13
echo "Test1" >> dir1/test1/test11/t1.txt
echo "Test2" >> dir1/test1/test12/t2.txt
echo "Test3" >> dir1/test1/test13/t3.txt

#And a dir to work in
mkdir gitdir

Geben Sie dann das Verzeichnis ein und importieren Sie das Verzeichnis 1

cd gitdir/
git init .
cp -r ../dir1/* .
git add .
git commit -m 'dir1'

Geh raus und ändere dir1 (so wird es dein dir2)

cd ..
echo "Test2" > dir1/test1/test11/t1.txt

Dann gehe in das Git-Verzeichnis und importiere das neue Verzeichnis

cd gitdir/
cp -r ../dir1/* .

Jetzt frag git was sich geändert hat (mit dem status Befehl)

git status -s

Die Ausgabe ist eine Liste mit den Änderungen, die so aussieht:

 M test1/test11/t1.txt

0

Vielleicht wären Sie mit etwas anderem glücklicher. Versuchen Sie es git.

Tun Sie dies als Beispiel:

mkdir a
cd a
git init
touch b
git add . && git commit -m "Empty file"
git status
echo c >> b
git status
git add . && git commit -m "Full file"
git status

gitverfolgt Ihre Dateien für Sie. Der Befehl git statuszeigt Ihnen alle Dateien an, die seit dem letzten Festschreiben geändert wurden.


0

Dies ähnelt rsync: show, wenn eine neuere Datei auf dem Ziel überschrieben werden soll (wird später gefragt, obwohl es sich nicht um ein Duplikat handelt).

Wie in der Frage angegeben, erfordert "diff -q -r" möglicherweise eine gewisse Verarbeitung, um nützlich zu sein. In der Frage wurde die Form der Ausgabe nicht angegeben. Die Antworten geben verschiedene Arten von Berichten.

rsyncist ein nützliches Werkzeug für diesen Zweck, weil es viel schneller ist als diff. Die von @nils vorgeschlagene Lösung ist jedoch weitaus ausführlicher (und listet mehr Dateien auf) als die tatsächlichen Unterschiede zwischen den alten / neuen Verzeichnisbäumen. Wenn Sie das zum Beispiel mit dem Skript vergleichen, das ich für diese Antwort geschrieben habe, und mit denselben Daten arbeiten,

  • @nils answer erzeugt 605 Zeilen (anscheinend, weil es Verzeichnisänderungen enthält ),
  • "diff -q -r" erzeugt nach einigen Minuten Laufzeit 352 Zeilen und
  • Mein Skript zeigt 252 Zeilen ( aktuelle Dateien geändert, hinzugefügt oder gelöscht)

Um neue Dateien diffrichtig zu berücksichtigen , benötigen Sie ebenfalls die Option (die ich in keiner der vorgeschlagenen Antworten sehe). Da es jedoch viel langsamer ist (um Größenordnungen) , scheint es der richtige Weg zu sein, die Leistung des letzteren zu verbessern.-Nrsync

Weitere Lektüre


0

Ich war schon immer ein Teil von sha1sum (oder sogar md5sum; in diesem Zusammenhang ist es ziemlich sicher).

find . -type f -print0 | xargs -0 md5sum | sort -k2 > /tmp/before
# don't miss the "sort" in there; it's important

# (later)
find . -type f -print0 | xargs -0 md5sum | sort -k2 > /tmp/after
vimdiff /tmp/before /tmp/after
# or whatever diff tool you like, even "diff -u"

Manchmal - zum Beispiel, wenn zu viele Dateien umbenannt oder verschoben wurden - kann es hilfreich sein, das erste Feld zu sortieren und dann den Vergleich durchzuführen. Meistens ist dies jedoch ausreichend.

Beachten Sie, dass dies im Vergleich zu einigen anderen Methoden den Vorteil hat, dass Sie keine Kopie der "Vorher" -Dateien aufbewahren müssen. nur die md5sum-ausgabedatei.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.