Unter Linux readlink
akzeptiert das Dienstprogramm eine Option-f
, die zusätzlichen Links folgt. Dies scheint auf Mac- und möglicherweise BSD-basierten Systemen nicht zu funktionieren. Was wäre das Äquivalent?
Hier sind einige Debug-Informationen:
$ which readlink; readlink -f
/usr/bin/readlink
readlink: illegal option -f
usage: readlink [-n] [file ...]
readlink
sich um einen integrierten oder einen externen Befehl handeln kann.touch myfile ; ln -s myfile otherfile ; perl -MCwd=abs_path -le 'print abs_path readlink(shift);' otherfile
tippe : ... in meinem Fall sehe ich: / Users / cito / myfile`. Fügte es meiner Antwort unten hinzu. Prost.Antworten:
readlink -f
macht zwei Dinge:Wenn Sie möchten, können Sie einfach ein Shell-Skript erstellen, das das Vanille-Readlink-Verhalten verwendet, um dasselbe zu erreichen. Hier ist ein Beispiel. Natürlich können Sie dies in Ihr eigenes Skript einfügen, in dem Sie anrufen möchten
readlink -f
Beachten Sie, dass dies keine Fehlerbehandlung beinhaltet. Von besonderer Bedeutung ist, dass Symlink-Zyklen nicht erkannt werden. Eine einfache Möglichkeit, dies zu tun, besteht darin, zu zählen, wie oft Sie die Schleife durchlaufen und fehlschlagen, wenn Sie eine unwahrscheinlich große Zahl treffen, z. B. 1.000.
BEARBEITET, um
pwd -P
anstelle von zu verwenden$PWD
.Beachten Sie, dass dieses Skript voraussichtlich wie folgt heißt
./script_name filename
: Nein-f
, ändern Sie$1
zu,$2
wenn Sie es mit einem-f filename
ähnlichen GNU-Readlink verwenden möchten.quelle
foo -> /var/cux
, dannfoo/bar
wird nicht gelöst, weilbar
es sich nicht um einen Linkfoo
handelt.cd "$(dirname "$TARGET_FILE")"
undTARGET_FILE=$(readlink "$TARGET_FILE")
undTARGET_FILE=$(basename "$TARGET_FILE")
an den entsprechenden Stellen im obigen Code.MacPorts und Homebrew bieten ein Coreutils- Paket mit
greadlink
(GNU-Readlink). Dank an Michael Kallweitt Beitrag in mackb.com.quelle
.bashrc
:export PATH="/usr/local/opt/coreutils/libexec/gnubin:$PATH"
pwd -P
undreadlink
unter OS X verwenden, ohne etwas zu installierenPATH
. Hat das oben mit angefangenbrew install <package> --default-names
. Oft wurde eine Frage auf dieser Website geringfügig oder mehr außerhalb der technischen Anforderungen des Fragestellers beantwortet, jedoch innerhalb einer ähnlichen Situation, und war dennoch sehr hilfreich. topbug.net/blog/2013/04/14/…Sie könnten interessiert sein
realpath(3)
oder Pythonsos.path.realpath
. Die beiden sind nicht genau gleich; Für den Aufruf der C-Bibliothek müssen zwischengeschaltete Pfadkomponenten vorhanden sein, für die Python-Version jedoch nicht.Ich weiß, dass Sie gesagt haben, Sie würden etwas Leichteres als eine andere Skriptsprache bevorzugen, aber nur für den Fall, dass das Kompilieren einer Binärdatei unerträglich ist, können Sie Python und ctypes (verfügbar unter Mac OS X 10.5) verwenden, um den Bibliotheksaufruf zu beenden:
Ironischerweise sollte die C-Version dieses Skripts kürzer sein. :) :)
quelle
realpath
ist in der Tat was ich will. Aber es scheint ziemlich umständlich, dass ich eine Binärdatei kompilieren muss, um diese Funktion aus einem Shell-Skript zu erhalten.readlink
selbst, oder?)python -c "import os,sys; print(os.path.realpath(os.path.expanduser(sys.argv[1])))" "${1}"
arbeitet mit Pfaden wie'~/.symlink'
perl -MCwd=abs_path -le 'print abs_path readlink(shift);'
meine Antwort ergänzen :-)Ich hasse es, mich mit einer weiteren Implementierung zu beschäftigen, aber ich brauchte a) eine tragbare, reine Shell-Implementierung und b) eine Unit-Test-Abdeckung , da die Anzahl der Randfälle für so etwas nicht trivial ist .
Siehe mein Projekt auf Github Tests und vollständigen Code. Was folgt, ist eine Zusammenfassung der Implementierung:
Keith Smith weist scharfsinnig darauf hin,
readlink -f
dass er zwei Dinge tut: 1) Symlinks rekursiv auflöst und 2) das Ergebnis kanonisiert, daher:Zunächst die Implementierung des Symlink-Resolvers:
Beachten Sie, dass dies eine leicht vereinfachte Version der vollständigen Implementierung ist . Die vollständige Implementierung fügt eine kleine Überprüfung für Symlink-Zyklen hinzu und massiert die Ausgabe ein wenig.
Schließlich die Funktion zum Kanonisieren eines Pfades:
Das war's mehr oder weniger. Einfach genug, um in Ihr Skript eingefügt zu werden, aber schwierig genug, dass Sie verrückt wären, sich auf Code zu verlassen, der keine Komponententests für Ihre Anwendungsfälle enthält.
quelle
local
Schlüsselwortreadlink -f
noch vonrealpath
. Angenommen, auf einem Mac ist die Coreutils-Formel installiert (alsogreadlink
verfügbar). Versuchen Sie dies mitln -s /tmp/linkeddir ~/Documents
;greadlink -f /tmp/linkeddir/..
druckt Ihr Home - Verzeichnis (es die aufgelöste/tmp/linkeddir
Verbindung , bevor Sie die Anwendung..
Elternverzeichnis ref), aber Ihr Code erzeugt/private/tmp/
wie/tmp/linkeddir/..
kein symbolischer Link ist, aber-d /tmp/linkeddir/..
wahr ist , und socd /tmp/linkeddir/..
nimmt man an/tmp
, deren kanonische Weg ist/private/tmp
. Ihr Code machtrealpath -L
stattdessen das, was er tut.Ein einfacher Einzeiler in Perl, der sicher fast überall ohne externe Abhängigkeiten funktioniert:
Wird dereferenzieren Symlinks.
Die Verwendung in einem Skript könnte folgendermaßen aussehen:
quelle
-l
, wieperl -MCwd -le 'print Cwd::abs_path shift' ~/non-absolute/file
greadlink ist der gnu-readlink, der -f implementiert. Sie können auch Macports oder andere verwenden, ich bevorzuge Homebrew.
quelle
Ich habe persönlich ein Skript namens realpath erstellt, das ungefähr so aussieht:
quelle
sys.argv[1]
wenn das Skript den Realpfad des ersten Arguments drucken soll.sys.argv[0]
druckt nur den tatsächlichen Pfad des Pyton-Skripts selbst aus, was nicht sehr nützlich ist.~/.profile
:alias realpath="python -c 'import os, sys; print os.path.realpath(sys.argv[1])'"
readlink -f
, ist hier eine modifizierte Version des Alias von @jwhitlock, um mögliche-f
Flaggen zu unterstützen :alias realpath="python -c 'import os, sys; print os.path.realpath(sys.argv[2] if sys.argv[1] == \"-f\" else sys.argv[1])'"
Was ist damit?
quelle
../../../
->/
/usr/bin/
wie ihn dasalternatives
System gerne hat.Hier ist eine tragbare Shell-Funktion, die in JEDEM funktionieren sollte vergleichbaren Bourne- . Die relative Pfadpunktion ".. oder" wird aufgelöst. und Dereferenzierung symbolischer Links.
Wenn Sie aus irgendeinem Grund keinen Befehl realpath (1) oder readlink (1) haben, kann dies ein Alias sein.
Genießen:
Für den Fall, dass sich hier jemand interessiert, erfahren Sie, wie Sie den Basisnamen und den Verzeichnisnamen in 100% reinem Shell-Code implementieren:
Eine aktualisierte Version dieses Shell-Codes finden Sie auf meiner Google-Website: http://sites.google.com/site/jdisnard/realpath
BEARBEITEN: Dieser Code ist unter den Bedingungen der 2-Klausel-Lizenz (FreeBSD-Stil) lizenziert. Eine Kopie der Lizenz finden Sie unter dem obigen Hyperlink zu meiner Website.
quelle
FreeBSD und OSX haben eine
stat
von NetBSD abgeleitete Version .Sie können die Ausgabe mit Formatschaltern anpassen (siehe die Handbuchseiten unter den obigen Links).
Bei einigen OS X-Versionen von
stat
fehlt möglicherweise die-f%R
Option für Formate. In diesem Fall-stat -f%Y
kann ausreichen. Die-f%Y
Option zeigt das Ziel eines Symlinks an, während-f%R
der absolute Pfadname der Datei angezeigt wird.BEARBEITEN:
Wenn Sie Perl verwenden können (Darwin / OS X wird mit den neuesten Versionen von installiert
perl
), dann:wird funktionieren.
quelle
R
Option zu-f%
fehlt. Gibt möglicherweisestat -f%Y
die gewünschte Ausgabe. Ich werde die Antwort anpassen. Beachten Sie, dass dasstat
Tool in FreeBSD in Version 4.10 und NetBSD in Version 1.6 angezeigt wurde.Der einfachste Weg, um dieses Problem zu lösen und die Funktionalität von Readlink auf einem Mac mit installiertem Homebrew oder FreeBSD zu aktivieren, ist die Installation des Pakets 'coreutils'. Kann auch unter bestimmten Linux-Distributionen und anderen POSIX-Betriebssystemen erforderlich sein.
In FreeBSD 11 habe ich beispielsweise Folgendes installiert:
# pkg install coreutils
Unter MacOS mit Homebrew lautet der Befehl:
$ brew install coreutils
Ich bin mir nicht sicher, warum die anderen Antworten so kompliziert sind, das ist alles. Die Dateien befinden sich nicht an einem anderen Ort, sie sind nur noch nicht installiert.
quelle
brew install coreutils --with-default-names
um genauer zu sein. Oder Sie werden stattdessen mit "greadlink" enden ...pwd -P
ist ziemlich einfach, aber es verschwindet unter vielen anderen Antworten, einschließlich wiederholter, daher die Abwertung.Update starten
Dies ist ein so häufiges Problem, dass wir eine Bash 4-Bibliothek zur freien Nutzung (MIT-Lizenz) namens realpath-lib zusammengestellt haben . Dies dient standardmäßig zur Emulation von readlink -f und umfasst zwei Testsuiten , um zu überprüfen, (1) ob es für ein bestimmtes Unix-System funktioniert und (2) gegen readlink -f, falls installiert (dies ist jedoch nicht erforderlich). Darüber hinaus kann es verwendet werden, um tiefe, unterbrochene Symlinks und Zirkelverweise zu untersuchen, zu identifizieren und abzuwickeln, sodass es ein nützliches Werkzeug zur Diagnose tief verschachtelter physischer oder symbolischer Verzeichnis- und Dateiprobleme sein kann. Es kann bei github.com oder bitbucket.org gefunden werden .
Update beenden
Eine weitere sehr kompakte und effiziente Lösung, die nur auf Bash basiert, ist:
Dies umfasst auch eine Umgebungseinstellung
no_symlinks
, mit der Symlinks zum physischen System aufgelöst werden können. Solangeno_symlinks
auf etwas eingestellt ist, werdenno_symlinks='on'
dann Symlinks zum physischen System aufgelöst. Andernfalls werden sie angewendet (Standardeinstellung).Dies sollte auf jedem System funktionieren, das Bash bereitstellt, und gibt zu Testzwecken einen Bash-kompatiblen Exit-Code zurück.
quelle
Es gibt bereits viele Antworten, aber keine hat bei mir funktioniert ... Das ist es also, was ich jetzt benutze.
quelle
$target
es sich um einen Pfad handelt, sondern nur, wenn es sich um eine Datei handelt.Ein fauler Weg, der für mich funktioniert,
quelle
Besser spät als nie, nehme ich an. Ich war motiviert, dies speziell zu entwickeln, weil meine Fedora-Skripte auf dem Mac nicht funktionierten. Das Problem sind Abhängigkeiten und Bash. Macs haben sie nicht oder wenn doch, sind sie oft woanders (auf einem anderen Weg). Die Manipulation von Abhängigkeitspfaden in einem plattformübergreifenden Bash-Skript bereitet bestenfalls Kopfschmerzen und im schlimmsten Fall ein Sicherheitsrisiko. Vermeiden Sie daher nach Möglichkeit deren Verwendung.
Die Funktion get_realpath () unten ist einfach, Bash-zentriert und es sind keine Abhängigkeiten erforderlich. Ich benutze nur die Bash Builtins Echo und CD . Es ist auch ziemlich sicher, da in jeder Phase des Weges alles getestet wird und Fehlerbedingungen zurückgegeben werden.
Wenn Sie keinen Symlinks folgen möchten, setzen Sie set -P an die Vorderseite des Skripts. Andernfalls sollte cd die Symlinks standardmäßig auflösen. Es wurde mit Dateiargumenten getestet, die {absolute | sind relativ | symlink | local} und gibt den absoluten Pfad zur Datei zurück. Bisher hatten wir keine Probleme damit.
Sie können dies mit anderen Funktionen get_dirname, get_filename, get_stemname und validate_path kombinieren. Diese finden Sie in unserem GitHub-Repository als realpath-lib (vollständige Offenlegung - dies ist unser Produkt, aber wir bieten es der Community kostenlos und ohne Einschränkungen an). Es könnte auch als Lehrmittel dienen - es ist gut dokumentiert.
Wir haben unser Bestes versucht, um sogenannte "moderne Bash" -Praktiken anzuwenden, aber Bash ist ein großes Thema, und ich bin sicher, dass es immer Raum für Verbesserungen geben wird. Es erfordert Bash 4+, kann aber auch für ältere Versionen verwendet werden, wenn diese noch vorhanden sind.
quelle
Da meine Arbeit von Leuten mit Nicht-BSD-Linux sowie MacOS verwendet wird, habe ich mich für die Verwendung dieser Aliase in unseren Build-Skripten entschieden (
sed
enthalten, da es ähnliche Probleme gibt):Optionale Überprüfung, die Sie hinzufügen können, um Homebrew + Coreutils- Abhängigkeiten automatisch zu installieren :
Ich nehme an, um wirklich "global" zu sein, muss es andere überprüfen ... aber das kommt wahrscheinlich der 80/20-Marke nahe.
quelle
Erläuterung
coreutils ist ein
brew
Paket, das GNU / Linux-Kerndienstprogramme installiert, die der Mac OSX-Implementierung entsprechen, damit Sie diese verwenden könnenMöglicherweise finden Sie Programme oder Dienstprogramme auf Ihrem Mac OSX-System, die Linux-Coreutils ("Core Utilities") ähneln, sich jedoch in einigen Punkten unterscheiden (z. B. mit unterschiedlichen Flags).
Dies liegt daran, dass die Mac OSX-Implementierung dieser Tools unterschiedlich ist. Um das ursprüngliche GNU / Linux-ähnliche Verhalten zu erhalten, können Sie das
coreutils
Paket über dasbrew
Paketverwaltungssystem installieren.Dadurch werden die entsprechenden Kerndienstprogramme installiert, denen ein Präfix vorangestellt ist
g
. Zum Beispielreadlink
finden Sie ein entsprechendesgreadlink
Programm.Um eine
readlink
Leistung wie bei der Implementierung von GNUreadlink
(greadlink
) zu erzielen, können Sie nach der Installation von coreutils einen einfachen Alias erstellen.Implementierung
Folgen Sie den Anweisungen unter https://brew.sh/
brew install coreutils
Sie können Ihren Alias in ~ / .bashrc, ~ / .bash_profile oder überall dort platzieren, wo Sie es gewohnt sind, Ihre Bash-Aliase zu behalten. Ich persönlich behalte meine in ~ / .bashrc
alias readlink=greadlink
Sie können ähnliche Aliase für andere Coreutils wie gmv, gdu, gdf usw. erstellen. Beachten Sie jedoch, dass das GNU-Verhalten auf einem Mac-Computer für andere, die mit nativen Coreutils arbeiten, verwirrend sein oder sich auf Ihrem Mac-System auf unerwartete Weise verhalten kann.
quelle
Ich habe ein Realpath-Dienstprogramm für OS X geschrieben, das die gleichen Ergebnisse liefern kann wie
readlink -f
.Hier ist ein Beispiel:
Wenn Sie MacPorts verwenden, können Sie es mit dem folgenden Befehl installieren :
sudo port selfupdate && sudo port install realpath
.quelle
Wirklich plattformunabhängig wäre auch dieser R-Onliner
Um tatsächlich nachzuahmen
readlink -f <path>
, müssten 2 USD anstelle von 1 USD verwendet werden.quelle
POSIX-kompatible
readlink -f
Implementierung für POSIX-Shell-Skriptehttps://github.com/ko1nksm/readlinkf
Dies ist POSIX-konform (kein Bashismus). Es verwendet keine
readlink
nochrealpath
. Ich habe durch Vergleich mit GNU bestätigt, dass es genau dasselbe istreadlink -f
(siehe Testergebnisse ). Es hat Fehlerbehandlung und gute Leistung. Sie können sicher von ersetzenreadlink -f
. Die Lizenz ist CC0, sodass Sie sie für jedes Projekt verwenden können.Bitte beziehen Sie sich auf den neuesten Code. Es kann einige behoben sein.
quelle
Perl hat eine Readlink-Funktion (z. B. Wie kopiere ich symbolische Links in Perl? ). Dies funktioniert auf den meisten Plattformen, einschließlich OS X:
Zum Beispiel:
quelle
readlink
ohne die-f
Option - keine Rekursion, kein absoluter Pfad -, also können Sie es auch verwendenreadlink
direkt können.Die Antwort von @Keith Smith gibt eine Endlosschleife.
Hier ist meine Antwort, die ich nur unter SunOS verwende (SunOS vermisst so viele POSIX- und GNU-Befehle).
Es ist eine Skriptdatei, die Sie in eines Ihrer $ PATH-Verzeichnisse einfügen müssen:
quelle
Das benutze ich:
stat -f %N $your_path
quelle
Die Pfade zum Readlink unterscheiden sich zwischen meinem und Ihrem System. Bitte geben Sie den vollständigen Pfad an:
quelle
readlink
ist gnu kompatibel. Das ist schön zu wissen, aber es löst mein Problem nicht, da ich mein Skript brauche, um auf dem Computer anderer Leute ausgeführt zu werden, und ich kann nicht verlangen, dass sie dafür fink installieren.