Wie kann ich 'diff -X' dazu bringen, bestimmte Pfade und nicht Dateinamen zu ignorieren?

28

Tun: diff -r -X <ignore-list> <src-dir> <dest-dir>

scheint keine diffignorierten Eingaben zu machen , <ignore-list>wenn sie von der Form sind <dir>/<file>.

Einträge des Formulars <file> werden jedoch berücksichtigt. Dies ist ein Problem, da ich möglicherweise mehrere Dateien <file>in verschiedenen Unterverzeichnissen habe, von denen einige nicht ignoriert werden sollen.

Es scheint auch nicht viele Informationen bezüglich der Mustersyntax in der Manpage zu geben diff. Soweit ich weiß, ist es nur der Basisname einer Datei, die von diff berücksichtigt wird (siehe http://forums.gentoo.org/viewtopic-t-889788-start-0.html, wenn Sie interessiert sind).

Asche
quelle
Mann, diffdie --excludeOption ist so beschissen ...
Elouan Keryell-Even

Antworten:

30

Verzeichnisse auflisten sollte funktionieren; zB hier ist, was ich in einem Skript verwendet habe (unter der Annahme, Gnu Diff),

diff -r \
   --exclude="*~" \
   --exclude=".svn" \
   --exclude=".git" \
   --exclude="*.zip*" \
   --exclude="*.gz" \
   --exclude="*.tar" \
   ...etc

... ignoriert den Inhalt von .svnund .gitdirs, aber auch einzelne Dateien mit dem Namen *.zip/ *.gz/ etc.

Bearbeiten: Um Pfade des Formulars, dir_a/file1aber immer noch diffDateien mit demselben Basisnamen zu filtern , wie z. B. dir_b/file1oder dir_a/b/file1, muss eine Liste der Dateien differstellt werden (z. B. mithilfe von find), und die zu vergleichende Datei muss aus diesen Pfaden abgeleitet werden. zB gegeben

$ find ONE TWO -type f -print 
ONE/a/1.txt
ONE/a/2.txt
ONE/a/b/2.txt
TWO/a/1.txt
TWO/a/2.txt
TWO/a/b/2.txt

Sie generieren die Liste der zu vergleichenden Dateien, ohne beispielsweise */a/2.txtandere Dateien mit dem Namen zu vergleichen 2.txt. "Finde" einfach alle Dateien außer ONE/a/2.txt(ein regulärer Ausdruck kann auch hier verwendet werden, wie zum Beispiel .*/a/2.txt)

$ find ONE -type f \( ! -regex 'ONE/a/2.txt' \) \
    -exec bash -c 'diff -q "${1}" "${2/ONE/TWO}"' - {} {} \;  

die in der Tat ignoriert ONE/a/2.txt(und TWO/a/2.txt), vergleicht aber immer noch die anderen genannten Dateien 2.txt:

diff -q ONE/a/1.txt TWO/a/1.txt
diff -q ONE/a/b/2.txt TWO/a/b/2.txt

Bearbeiten: Oder, mehr Spaß mit find(zusätzlicher Spaß als Übung für den Leser), wählen Sie die Dateien oder Verzeichnisse aus, die Sie ausschließen möchten, und dann diffalles andere:

$ find ONE \( -regex 'ONE/a/2.txt' -o -name b  -prune \)  \
    -o -type f -exec bash -c 'echo diff -q "${1}" "${2/ONE/TWO}"' - {} {} \

Das obige Beispiel schließt die spezifische Datei "{top} /a/2.txt", ein beliebiges Verzeichnis mit dem Namen "b" aus und alles andere ist anders. (Anstelle von " -name b" einfach könnte man auch " -regex '.*/b'" - not, no trailing "/" verwenden.)

michael
quelle
2
Danke, aber ich denke, Sie verpassen den Punkt. Es scheint nur Unterstützung zu geben, wenn Sie einen Basisnamen verwenden. Das kann der Name eines Verzeichnisses oder einer Datei sein. In beiden Fällen ignoriert diff, wonach Sie gefragt haben. Das Problem tritt auf, wenn Sie Pfade verwenden. Zum Beispiel kann ich diff nicht dazu bringen, / an / absolute / path / to / a / file oder ./a/relative/path/to/a/file zu ignorieren.
Asche
2
diff --exclude = "/ this / specific / file / that / im / explizit / plädierend / you / to / ignore". Es wird nicht funktionieren.
Asche
3
Richtig, excludeMuster werden mit dem Basisnamen der Dateien abgeglichen (gemäß gnu.org/software/diffutils/manual/html_node/… ). Pfade funktionieren nicht (wie in foo/bar.txt). Dazu müssen Sie wahrscheinlich finddie Liste der Dateinamen erstellen und den Pfad zu der zu vergleichenden Datei ableiten.
Michael
Die Antwort wurde aktualisiert, um ein Beispiel diffbasename
einzuschließen
Okay, ich verstehe, was Sie vorschlagen, aber es scheint ein Problem zu geben. Ich muss auch Verzeichnisse berücksichtigen, nicht nur Dateien (dh -type f). Sie können zwar weiterhin bestimmte Dateien mit regexp mit bereinigen find, aber wenn die Eingabe diffein Verzeichnis enthält, werden die Dateien in diesem Verzeichnis durchsucht und verglichen. Einige dieser Dateien müssen möglicherweise ignoriert werden zurück zu Platz 1.
Asche
1

Um Verzeichnis auszuschließen directory/sub-directory, benutze ich

diff -r <src-dir> <dest-dir> | grep -v directory/sub-directory

Obwohl es für einen einzelnen Ausschluss funktionieren sollte, sollte es für eine lange Ignorierliste nicht möglich sein, wie Sie es getan haben.

Elouan Keryell-Even
quelle
-2
$ diff -rq foo.orig foo | grep -vP 'ignore1/|exclude2/' | awk '{print $2}' | cut -d'/' -f2- | xargs -I{} diff -u foo.orig/{} foo/{}
vern
quelle
1
Während dies die Frage beantworten mag, wäre es eine bessere Antwort, wenn Sie eine Erklärung dafür liefern könnten .
DavidPostill