Heiß darauf, einen Symlink-Link selbst zu überprüfen?

8

Unter Linux kann man mit dem Befehl diffnach Unterschieden bei Dateien suchen. Ich benutze es, um nach Unterschieden zwischen zwei Modulen zu suchen, die beide kopiert wurden /tmp.

Beide Module verfügen jedoch über Symlinks, die möglicherweise nicht auf die richtige Datei verweisen, da die Module in das /tmpVerzeichnis kopiert wurden . Das spielt aber keine Rolle. Ich möchte überprüfen, ob die Symlinks identisch sind.

In einem Modul lautet beispielsweise der Symlink

/home/test/file1

und im anderen lautet der Symlink:

/etc/rc.d/whatever

diffJetzt wird ein Fehler ausgegeben, da die Datei im Allgemeinen nicht gefunden werden kann. Aber ich möchte diffsagen lassen : "Hey, diese Symlinks sind nicht gleich", unabhängig davon, ob die Links auf gültige Dateien verweisen oder nicht.

Frage: Wie ist es möglich diff, dies zu tun, dh nicht zu versuchen, Links zu folgen, sondern die Links selbst zu unterscheiden?

Alex
quelle

Antworten:

6

Versuchen Sie GNU diffVersion 3.3 oder höher mit der --no-dereferenceOption (und vermutlich der Option --recursive):

diff --recursive --no-dereference tree1root tree2root
Britton Kerin
quelle
Könnten Sie das ein wenig ausarbeiten? Vielleicht ein Beispiel geben, wie es verwendet werden könnte? Dies hat das Zeug zu einer vollkommen guten Antwort, aber wir möchten, dass unsere Antworten hier etwas expliziter und ausführlicher sind.
Terdon
3

Seit Version 3.3 unterstützt GNU diff nicht die Dereferenzierung von Symlinks, sondern vergleicht dann die Pfade, auf die sie zeigen.

Installieren Sie GNU diffutils> = 3.3 und verwenden Sie die Option '--no-dereference'. Dafür gibt es keine kurze Option.

Die Diagnose ist stumm, wenn die Pfade gleich sind, oder:

Symbolic links /tmp/noderef/a/symlink and /tmp/noderef/b/symlink differ

wenn sich die Pfade unterscheiden.

Philippe De Muyter
quelle
1

Mit GNU-Tools:

diff <(cd dir1 && find . -type l -printf '%p -> %l\n'|sort) \
     <(cd dir2 && find . -type l -printf '%p -> %l\n'|sort)

Genau genommen kann das nicht zwischen einem Symlink, der auf adiesen Punkt verweist, b -> cund einem Symlink, der auf diesen Punkt a -> bverweist, unterscheiden c, ganz zu schweigen von den Problemen mit Dateinamen, die Zeilenumbrüche enthalten. Dies führt jedoch zu einer besser lesbaren Ausgabe als der robusteren:

diff <(cd dir1 && find . -type l -printf '%p // %l\0'|tr '\n\0' '\0\n'|sort) \
     <(cd dir2 && find . -type l -printf '%p // %l\0'|tr '\n\0' '\0\n'|sort)

Dort verwenden wir //als Trennzeichen (das sonst in der Ausgabe von findfor nicht vorkommen kann %p) und konvertieren die Zeilenumbruchzeichen in NUL-Zeichen (die bei der Erweiterung von %pnor nicht vorkommen können %l).

Stéphane Chazelas
quelle
1

Wenn ich das richtig verstehe, möchten Sie überprüfen, ob die Symlinks auf dasselbe theoretische Ziel verweisen oder ob die andere Datei auf dieselbe Datei verweist, wenn einer kein Symlink ist. Dies sollte tun, was Sie wollen:

#!/bin/bash

if [[ "$(readlink -m -- "$1")" == "$(readlink -m -- "$2")" ]]; then
    echo "files match"
else
    echo "files don't match"
    exit 1
fi
$ > foo 
$ ln -s foo bar
$ ln -s foo baz
$ ./script bar baz
files match
$ ./script bar foo
files match
$ ln -sf qux bar
$ ./script bar foo
files don't match
Chris Down
quelle
@StephaneChazelas Das ist mein Fehler, den ich verwenden wollte -m, nicht -f. Vielen Dank!
Chris Down
Genau genommen würde das nicht funktionieren, wenn der einzige Unterschied in der Anzahl der nachgestellten Zeilenumbrüche in den Zielen der Symlinks besteht.
Stéphane Chazelas
Ich würde auch nicht verwenden -m.
Stéphane Chazelas
@StephaneChazelas Aus welchem ​​Grund? Ohne diese Option können relative Symlinks, die wirklich auf dieselbe Datei verweisen, diesen Vergleich nicht bestehen.
Chris Down
Wenn /home/test/file1ein Symlink zu /etc/rc.d/whateveroder beide ein Symlink zu sind /, wird gemeldet, dass sie gleich sind. Ich denke, das OP möchte den Unterschied im "Pfad" sehen, der im Symlink gespeichert ist, und nicht, ob sie in dieselbe Datei aufgelöst werden (für die Sie haben [[ a -ef b ]]).
Stéphane Chazelas