Was ist ein portabler Weg für ein (zsh) Skript, um seinen absoluten Pfad zu bestimmen?
Unter Linux verwende ich sowas
mypath=$(readlink -f $0)
... aber das ist nicht portabel. (ZB readlink
erkennt darwin das nicht-f
Flagge nicht und hat auch keine Entsprechung readlink
.)
Was ist portabler?
Antworten:
Mit
zsh
ist es nur:Nun aber zu anderen Shells
realpath()
und zureadlink()
Standardfunktionen (wobei letztere ein Systemaufruf ist)realpath
undreadlink
nicht zum Standardbefehl gehören, obwohl einige Systeme über die eine oder andere oder beide mit unterschiedlichem Verhalten und Funktionsumfang verfügen.Aus Gründen der Portabilität möchten Sie möglicherweise wie oft auf Folgendes zurückgreifen
perl
:Das würde sich eher wie bei GNU verhalten
readlink -f
alsrealpath()
(GNUreadlink -e
) , da es sich nicht beschwert, wenn die Datei nicht existiert, solange ihr Dirname existiert.quelle
.zshrc
: Siehe stattdessen diesen Beitrag .In zsh können Sie Folgendes tun:
Oder um das Verzeichnis abzurufen, in dem sich das Skript befindet:
Quelle: Manpage zshexpn (1), Abschnitt HISTORY EXPANSION, Unterabschnitt Modifiers (oder einfach
info -f zsh -n Modifiers
).quelle
readlink -f
wäre eher$0:A
.Ich benutze das jetzt seit einigen Jahren:
quelle
readlink -f
ist, wenn das Skript selbst ein Symlink ist.zsh
, wenn ich dies entweder direkt oder in der Subshell (wie vorgeschlagen) ausführe, während ich mich in meinem Home-Verzeichnis () befinde/home/ville
, wird es gedruckt/home/ville/zsh
.Diese Syntax sollte in jedem Stil Bourne - Shell - Interpreter tragbar sein (getestet mit
bash
,ksh88
,ksh93
,zsh
,mksh
,dash
undbusybox sh
):Diese Version fügt der älteren AT & T Bourne-Shell (nicht POSIX) Kompatibilität hinzu:
quelle
$PWD
ein Overkill sein könnte - Sie können es einfach auf den absoluten Strom wie einstellencd -P .
. Ich bezweifle, dass das in Bourneshell funktionieren würde - aber es sollte in allen funktionieren, die Sie für das erste Mal getestet haben. tut für mich sowiesozsh
unddirname
aber schnell seinen / ihren Kommentar zurückgezogen hat ...Angenommen, Sie meinen wirklich den absoluten Pfad, dh einen Pfad aus dem Stammverzeichnis:
Dies funktioniert übrigens in jeder Bourne-artigen Shell.
Wenn Sie einen Pfad gemeint haben, bei dem alle symbolischen Links aufgelöst sind, ist das eine andere Sache.
readlink -f
Funktioniert unter Linux (mit Ausnahme einiger reduzierter BusyBox-Systeme), FreeBSD, NetBSD, OpenBSD und Cygwin, jedoch nicht unter OS / X, AIX, HP / UX oder Solaris. Wenn Sie habenreadlink
, können Sie es in einer Schleife aufrufen:Wenn nicht
readlink
, können Sie es mit approximieren.ls -n
Dies funktioniert jedoch nur, wennls
der Dateiname keine nicht druckbaren Zeichen enthält.(Das Besondere
z
für den Fall, dass das Link-Ziel in einer neuen Zeile endet, die sonst durch eine Befehlsersetzung aufgebraucht würde. Dierealpath
Funktion behandelt diesen Fall übrigens nicht für Verzeichnisnamen.)quelle
ls
Implementierung, die nicht druckbare Zeichen entstellt, wenn die Ausgabe nicht an ein Terminal gesendet wird ?touch Stéphane; LC_ALL=C busybox ls Stéphane | cat
→St??phane
(Wenn der Name in UTF-8 steht, gibt latin1 eine Single aus?
). Ich glaube, das habe ich auch bei älteren kommerziellen Unices gesehen.busybox
ist das? laut gitbusybox ls
hat sich der code seit 2011 nicht mehr geändert. mybusybox ls
- circa 2013 - macht das nicht. Das eine - circa 2012 - tut . Dies könnte erklären, warum. Haben Sie Ihrebusybox
mit Unicode-Unterstützung erstellt - um wchar-Unterstützung einzuschließen? Vielleicht möchten Sie es ausprobieren, um die Build-Optionen immkinitcpio
busybox
Paket zu überprüfen .Vorausgesetzt, Sie haben Ausführungsberechtigungen für das aktuelle Verzeichnis - oder für das Verzeichnis, von dem aus Sie Ihr Shell-Skript ausgeführt haben -, wenn Sie nur einen absoluten Pfad zu einem Verzeichnis benötigen
cd
.Schritt 10 von
cd
's specUnd weiter
pwd -P
Es ist , weil
cd -P
hat das aktuelle Arbeitsverzeichnis zu setzen , waspwd -P
sollte sonst drucken und dascd -
hat zu drucken ,$OLDPWD
dass folgende Arbeiten:AUSGABE
warte darauf...
AUSGABE
Und wenn ich mit
cd -
drucke, drucke ich$OLDPWD
.cd
setzt$PWD
sobald ichcd -P .
$PWD
jetzt einen absoluten pfad dazu habe/
- also brauche ich keine weiteren variablen. Und eigentlich sollte ich nicht einmal die Hinter brauchen ,.
aber es gibt eine spezifizierte Verhalten Zurücksetzen$PWD
auf$HOME
in einer interaktiven Shell , wenncd
schmucklos ist. Es ist also nur eine gute Angewohnheit, sich zu entwickeln.Das oben aufgeführte Vorgehen auf dem Pfad in
${0%/*}
sollte also mehr als genug sein, um$0
den Pfad zu überprüfen , aber in dem Fall, dass$0
es sich selbst um einen Softlink handelt, können Sie das Verzeichnis leider nicht ändern.Hier ist eine Funktion, die das erledigt:
Es wird versucht, so viel wie möglich in der aktuellen Shell zu tun - ohne eine Subshell aufzurufen - obwohl Subshells für Fehler und Softlinks aufgerufen werden, die nicht auf Verzeichnisse verweisen. Es hängt von einer POSIX-kompatiblen Shell und einem POSIX-kompatiblen
ls
sowie einem sauberen_function()
Namespace ab. Ohne Letzteres funktioniert es immer noch einwandfrei, obwohl es dann möglicherweise überschrieben wirdunset
in diesem Fall einige aktuelle Shell-Funktionen . Im Allgemeinen sollten all diese Abhängigkeiten auf einer Unix-Maschine ziemlich zuverlässig verfügbar sein.Wird es mit oder ohne Argumente aufgerufen, wird es zunächst
$PWD
auf seinen kanonischen Wert zurückgesetzt. Dabei werden alle darin enthaltenen Verknüpfungen zu ihren Zielen nach Bedarf aufgelöst. Ohne Argumente angerufen und das war's auch schon; aber mit ihnen angerufen und es wird aufgelöst und kanonisiert den Pfad für jeden oder sonst eine Nachricht zu druckenstderr
warum nicht.Da es hauptsächlich in der aktuellen Shell ausgeführt wird, sollte es in der Lage sein, eine Argumentliste beliebiger Länge zu verarbeiten. Es sucht auch nach der
$_zdlm
Variablen (die es auch ist,unset
wenn sie durch ist) und gibt ihren C-escaped-Wert unmittelbar rechts von jedem seiner Argumente aus, auf die immer auch ein einzelnes\n
ewline-Zeichen folgt.Es macht eine Menge Verzeichnis zu ändern, aber, anders als es nach dem kanonischen Wert, ist es nicht beeinflussen
$PWD
, obwohl$OLDPWD
auf keinen Fall damit gerechnet werden kann, wann es fertig ist.Es versucht, jedes seiner Argumente so schnell wie möglich zu beenden. Es versucht zuerst
cd
hinein$1
. Wenn dies möglich ist, wird der kanonische Pfad des Arguments zu ausgegebenstdout
. Wenn dies nicht möglich ist, wird überprüft, ob$1
ein Softlink vorhanden ist. Wenn dies zutrifft, wird gedruckt.Auf diese Weise werden alle Dateitypargumente verarbeitet, zu deren Adressierung die Shell berechtigt ist, es
$1
sei denn, es handelt sich um einen symbolischen Link, der nicht auf ein Verzeichnis verweist. In diesem Fall wird diewhile
Schleife in einer Subshell aufgerufen.Es ruft
ls
auf, um den Link zu lesen. Das aktuelle Verzeichnis muss zuerst auf den Anfangswert geändert werden, damit referenzierte Pfade zuverlässig verarbeitet werden können. In der Subshell für die Befehlsersetzung führt die Funktion daher Folgendes aus:Es wird
ls
so wenig von der linken Seite der Ausgabe entfernt, wie es erforderlich ist, um den Namen des Links und die Zeichenfolge vollständig zu enthalten->
. Ich habe zunächst versucht, dies zu vermeiden,shift
und$IFS
es hat sich herausgestellt, dass dies die zuverlässigste Methode ist, soweit ich das beurteilen kann. Dies ist das gleiche, was Gilles ' poor_mans_readlink tut - und es ist gut gemacht.Dieser Vorgang wird in einer Schleife wiederholt, bis der zurückgegebene Dateiname
ls
definitiv kein Softlink mehr ist. An diesem Punkt kanonisiert es diesen Pfad wie zuvorcd
und druckt dann.Anwendungsbeispiel:
AUSGABE
Oder vielleicht ...
AUSGABE
quelle
Was ist mit einem sympathischen Einzeiler, wenn Python verfügbar ist, um zu verhindern, dass ein Algorithmus neu definiert wird?
Entspricht https://stackoverflow.com/a/7305217
quelle