Wie kann man mehrere Dateien über Verzeichnisse verteilen?

19

Ich versuche, diffs zwischen allen Dateien mit demselben Namen in zwei Kopien eines Verzeichnisses zu finden (z. B. eine Arbeits- und eine Sicherungskopie). Zum Beispiel kann ich diffzwei Dateien mit dem gleichen Namen in beiden:

> diff d1/f.cpp d2/f.cpp

oder ich kann Unterschiede zwischen den Verzeichnissen finden:

> diff d1 d2

aber wie kann ich Unterschiede nur zwischen den *.cppDateien finden?

> diff d1/*.cpp d2/*.cpp

scheint nicht zu funktionieren (aus offensichtlichen Gründen).

[Es ist wahrscheinlich leicht mit Schleifen zu lösen, aber ich versuche einen eleganteren Weg zu finden]

ysap
quelle

Antworten:

13

Sie können eine Shell-Schleife verwenden, die diff für jede Datei ausführt. Dies erfasst jedoch nicht die Fälle, in denen d2 eine Datei enthält, d1 jedoch nicht. Es könnte jedoch ausreichend sein.

for file in d1/*.cpp; do
    diff "$file" "d2/${file##*/}"
done

Oder alles in einer Zeile:

for file in d1/*.cpp; do diff "$file" "d2/${file##*/}"; done

Das ${file##*/}Teil ist eine spezielle Parametererweiterung.

Wenn die Dateivariable enthält d1/hello.cpp, "${file##*/}"wird auf erweitert hello.cpp(der Wert der Datei, jedoch mit allem, was bis einschließlich zum letzten / entfernten Wert reicht).

Das "d2/${file##*/}"Ergebnis d2/hello.cppist also und der resultierende Diff-Befehl ist somitdiff d1/hello.cpp d2/hello.cpp

Weitere Informationen zu Zeichenfolgenmanipulationen in der Bash finden Sie unter http://mywiki.wooledge.org/BashFAQ/100 .

Nebenbei bemerkt, ein Versionskontrollsystem (wie Subversion, Git, Mercurial usw.) würde diese Art der Unterscheidung viel einfacher machen.

geirha
quelle
Ich denke, dass von den zwei großartigen Antworten diese hier einfacher ist, wenn es mehrere Dateitypen gibt (obwohl ich in der Frage erwähnt habe, dass ich nach einer No-Loops-Lösung suche), also habe ich sie akzeptiert. Der eine Zusatz steht echo "${file##*/}";vor dem diffBefehl, damit man weiß, welche Dateien tatsächlich verglichen werden. Wie in der Antwort von @ Rinzwind erwähnt, deckt diese Methode auch nicht den Fall ab, in dem die Dateiliste in beiden Verzeichnissen nicht genau gleich ist.
YSAP
52

diff -qr {DIR1} {DIR2} erledigt alle Dateien in beiden Verzeichnissen.

  • q zeigt nur Unterschiede
  • rtut rekursiv. Lass es weg, wenn du das nicht brauchst

Sie können nicht diffdirekt angeben , dass Platzhalter verwendet werden sollen, aber Sie können Folgendes hinzufügen:

-x PAT  --exclude=PAT
    Exclude files that match PAT.

-X FILE    --exclude-from=FILE
   Exclude files that match any pattern in FILE.

Dateien ausschließen. Wenn Sie also nur *.cppdie einfachste Methode möchten , erstellen Sie eine Textdatei, in der alle nicht vorhandenen Dateien aufgelistet sind *.cpp. Sie können dies mit dem folgenden Befehl ausführen : ls -I "*.cpp" > excluded_filesDabei -I "*.cpp"ignoriert das Argument alle CPP-Dateien. Beachten Sie, dass die Anführungszeichen erforderlich sind.

Rinzwind
quelle
Einfach und funktioniert einwandfrei.
Jose Gómez
4

Einige Zeit nachdem ich die Frage gestellt hatte, fand ich das melddiff-Dienstprogramm heraus und benutze es seitdem. Dies ist ein großartiges GUI-basiertes Programm, das den Vergleich und das Zusammenführen von Dateien und Verzeichnissen zu einer sehr einfachen Aufgabe macht. Es werden Zwei- oder Dreiwege-Vergleiche durchgeführt.

Insbesondere beantwortet es meine ursprüngliche Frage, indem es Ihnen einen farbcodierten Vergleich des Verzeichnisinhalts zeigt und Sie bestimmte Dateien durch einen Doppelklick auf den Dateinamen vergleichen können.

Wenn man mehr als einen Drei-Wege-Vergleich benötigt, dann ist gvimdiff(basierend auf dem vimEditor) auch ein großartiger Vergleich, der diese Funktionalität bietet.

ysap
quelle
1

Dafür gibt es eine leichte Lösung:

  1. Richten Sie dieses kleine Plugin ein http://www.vim.org/scripts/script.php?script_id=5309
  2. Mach es diff dir1 dir2 | vim -R -in der Schale

Es werden Falzungen und ein direkter Vergleich für geänderte Dateien hinzugefügt.

Yuriy Ershov
quelle