Zeigen die folgenden Pfade auf denselben Speicherort?
/home/username
/app/home/username
Zeigen die folgenden Pfade auf denselben Speicherort?
/home/username
/app/home/username
Antworten:
Wechseln Sie nacheinander in jedes Verzeichnis und sehen Sie sich die Ausgabe von an pwd -P
. Mit dem -P
Flag pwd
wird das physische aktuelle Arbeitsverzeichnis mit allen aufgelösten symbolischen Links angezeigt.
cd -P
den aufgelösten Verzeichnisnamen verwenden könnten $PWD
) , wird das Problem separater Geräte nicht behandelt .
sd(){ set '' "$1" '' "${2?sd() requires two arguments!}"
while [ "$#" -gt 2 ]
do [ "${1:--L}" "${2:--L}" ${3:+"$4"} ] &&
[ "${1:--L}" ${3:+"-L"} "${3:-$4}" ] &&
[ "${2:-$3}" -ef "$4"/. ] && return || ${1:+"return"}
set "$@" "$2";shift 2;set ! "$@"
done 3>/dev/null 2>&"$((${#DBG}?2:3))"
}
sd()
Zuerst wird geprüft, ob beide Argumente Symlinks sind, und in diesem Fall wird geprüft, ob beide mit Verzeichnissen mit identischen Inode- und Gerätenummern verknüpft sind. Wenn ja, ist es sd()
return
wahr
Andernfalls wird überprüft, ob beide keine Symlinks sind und ob beide Verzeichnisse mit gleichen Geräte- und Inode-Nummern sind. Andernfalls wird false zurückgegeben.
Damit...
ln -s dir1 ln3; ln -s dir1 ln4; ln -s dir2 ln5
sd dir1 dir2; echo $?
1
sd dir1 ln3; echo $?
1
sd ln4 ln3; echo $?
0
sd ln4 ln5; echo $?
1
mount --bind dir1 dir2
sd dir1 dir2; echo $?
0
Es kann wünschenswert sein, auf die Linkprüfung zu verzichten - zum Beispiel, wenn Sie wissen möchten, ob das Ziel eines Links mit einem Verzeichnis identisch ist oder ob es sich überhaupt nicht um einen Link handelt. In diesem Fall benötigen Sie nur einen [ fname1 -ef fname2 ]
Test.
Oh, ich denke, ich sollte auch erwähnen, dass dies Suchberechtigungen für alle Argumente voraussetzt. Es schlägt fehl, wenn der aufrufende Benutzer nicht über die zum Ausführen des Tests erforderlichen Berechtigungen verfügt.
Sie können nie sicher sein, welcher Mechanismus oder welche virtuellen Dateisysteme oder Overlay-Dateisysteme vorhanden sind, um diese Ordner zu synchronisieren oder miteinander zu verknüpfen. Wenn es sich um eine einfache symbolische Verknüpfung handelt, unterscheiden sich die Inodes. Um 100% sicher zu stellen, dass es sich um denselben Speicherort handelt, können Sie eine Datei erstellen in /home/username
:
touch /home/username/.testfile
Vergleichen Sie dann die Inode-Nummern dieser Datei an beiden Speicherorten:
diff <(stat -c "%i" /home/username/.testfile) <(stat -c "%i" /app/home/username/.testfile)
Wenn sie gleich sind, handelt es sich um dieselbe Datei, daher verweisen sie auf denselben Speicherort.
Trotzdem können Sie nicht 100% sicher sein. Natürlich können sie zufällig die gleiche Inode-Nummer haben, denn in beiden Dateisystemen hatte die nächste freie Inode die gleiche Nummer ...
Es gibt zwei grundlegende Möglichkeiten, um zu überprüfen, ob zwei Dateien identisch sind. Der erste besteht darin, zu überprüfen, ob ihre Pfade gleich sind . Dies hat keine falsch positiven, aber viele falsch negative Ergebnisse. Ein offensichtlicher Fall von falsch negativen Ergebnissen ist, wenn symbolische Verknüpfungen beteiligt sind. Sie können diesen Fall behandeln, indem Sie die symbolischen Links auflösen. Für vorhandene Verzeichnisse, in die Sie wechseln dürfen, ist dies möglich pwd -P
.
absolute_path1="$(cd -- "$path1" && pwd -P; echo .)" &&
absolute_path2="$(cd -- "$path2" && pwd -P; echo .)" &&
[ "$absolute_path1" = "$absolute_path2" ]
Das Extra echo .
kümmert sich um den seltenen Fall, dass eines der Ziele einen Dateinamen hat, der mit einer neuen Zeile endet: Wenn die neue Zeile das letzte Zeichen der Befehlsersetzung wäre, würde sie entfernt, sodass das Snippet fälschlicherweise meldet, dass dies foo
dasselbe ist wie foo
.
Es gibt immer noch mögliche falsche Negative. Bei Verzeichnissen spielen feste Verknüpfungen keine Rolle, da die meisten Betriebssysteme und Dateisysteme das Verknüpfen von Verzeichnissen verbieten. Was passieren kann ist, dass dasselbe Verzeichnis irgendwie an verschiedenen Orten verfügbar gemacht wird, wie zum Beispiel:
Mounten des gleichen Remote-Dateisystems an zwei verschiedenen Orten, z
mount server:/some/where /mnt1
mount server:/some/where /mnt2
compare /mnt1 /mnt2
Ein Bind Mount
In diesen Beispielen ist fraglich, ob die Verzeichnisse wirklich gleich sind. Dies zeigt die Grenze des Begriffs "gleiche Datei" in Randfällen.
Die zweite grundlegende Möglichkeit besteht darin , die vom Kernel bereitgestellte Identifikation zu überprüfen: Gerät und Inode . Der stat
Systemaufruf meldet zwei Attribute für jede Datei:
st_dev
), die traditionell eine Identifikation des Blockgeräts (Festplattenpartition) ist, das das Dateisystem enthält, auf dem sich die Datei befindet;st_ino
), die traditionell eine eindeutige Nummer ist, die die Datei innerhalb desselben Dateisystems identifiziert.Normalerweise sind zwei Dateien genau dann identisch, wenn sie die gleichen Geräte- und Inode-Nummern haben. Dash, ksh, bash, zsh und zumindest einige BusyBox-Builds (aber nicht einfache POSIX sh) haben einen -ef
Operator für das test
eingebaute System, der Folgendes testet:
[ "$path1" -ef "$path2" ]
Dies behandelt Hardlinks und symbolische Links korrekt (symbolische Links werden befolgt, dh ein symbolischer Link zu einer Datei wird als derselbe wie die Zieldatei angesehen).
Diese Methode ist am einfachsten durchzuführen, wenn Ihre Shell (oder Ihr test
Dienstprogramm) dies unterstützt -ef
. Beachten Sie jedoch, dass es falsch positive Ergebnisse gibt, da nicht alle Dateisysteme eindeutige Inode-Nummern melden. Bei Netzwerkdateisystemen sind Sie beispielsweise der Wahl der Inode-Nummern des Remote-Hosts ausgeliefert. Viele stapelbare Dateisysteme melden den zugrunde liegenden Inode, der nicht eindeutig ist, wenn der zugrunde liegende Verzeichnisbaum mehrere Dateisysteme umfasst.
Ein anderer Ansatz besteht darin , die beobachtbare Äquivalenz zu testen : Ändern Sie eines der Verzeichnisse und prüfen Sie, ob sich die Änderung im anderen widerspiegelt. Dieser Ansatz hat im Prinzip keine falschen Negative, erfordert jedoch die Berechtigung zum Ändern der Verzeichnisse und kann andere Teile des Systems stören, die diese Verzeichnisse verwenden. Es kann zu Fehlalarmen kommen, da die angezeigten Änderungen darauf hinweisen können, dass ein Daemon die Verzeichnisse sehr schnell synchronisiert.
Unter der Annahme , /home/username
und /app/home/username
sind Verzeichnisse, können Sie die Inode - Nummer nicht überprüfen , um zu sehen , ob sie den gleichen Weg sind. Dies liegt daran, dass Verzeichnisse nicht fest verknüpft werden können und Softlinks einen anderen Inode aufweisen.
Sie könnten cd /home/username
, um touch
eine Datei, und sehen , ob es in der anderen erscheint /app/home/username
. Es gibt wahrscheinlich bessere Methoden. Wenn jemand eine bessere Antwort geben kann, fahren Sie bitte fort.
mount --bind
ein Verzeichnis haben, wird der Mount-Punkt mit demselben Inode aufgelistet. Gleiches gilt, wenn Sie ein Dateisystem an zwei Speicherorten bereitstellen. Ich habe dies gerade auf einem von Debian abgeleiteten System überprüft.
Wenn Sie das erweitern, was marco gesagt hat: Unter GNU / Linux erhalten ls -li /home/username /app/home/username
Sie bereits einen guten Hinweis . Wenn beide Inodes gleich wahrscheinlich sind, zeigen sie auf denselben Ort. Überprüfen Sie mit mount
. Überprüfen Sie touch
dreimal, /home/username
ob eine Datei in /app/home/username
und mit demselben Inode angezeigt wird . Dann kann ziemlich sicher sein, dass es das gleiche Verzeichnis ist.
Test auf einem Linux Mint-Computer, 3.11.0-12-generischer Kernel:
# ls -ldi /var
2 drwxr-xr-x 13 root root 4096 jan 13 2014 /var
# mkdir /mnt/var
# ls -ldi /mnt/var
266483 drwxr-xr-x 2 root root 4096 jun 2 10:43 /mnt/var
# mount --bind /var /mnt/var
# ls -ldi /mnt/var
2 drwxr-xr-x 2 root root 4096 jun 2 10:43 /mnt/var
# umount /mnt/var
# mount /dev/mapper/mint--vg-var /mnt/var
# ls -ldi /mnt/var
2 drwxr-xr-x 13 root root 4096 jan 13 2014 /mnt/var
Fazit: Ich denke, Sie können die Inodes überprüfen, um sicherzustellen, dass zwei Verzeichnisse identisch sind, vorausgesetzt, sie sind Mount-Punkte. Wenn es sich um eine symbolische Verknüpfung handelt, gilt das oben Gesagte natürlich nicht. Aber dann ist es offensichtlich, richtig:
# rmdir /mnt/var
# ln -s /var /mnt/
# ls -ldi /mnt/var
266483 lrwxrwxrwx 1 root root 4 jun 2 10:51 /mnt/var -> /var