realpathscheint auf dem Mac nicht verfügbar zu sein (OS X 10.11 "El Capitan"). :-(
Laryx Decidua
realpathscheint auch unter CentOS 6 nicht verfügbar zu sein
user5359531
6
auf osx, brew install coreutilswird inrealpath
Kevin Chen
Auf meinem Ubuntu 18.04 realpathist schon vorhanden. Ich musste es nicht separat installieren.
Acumenus
Überraschenderweise realpathist es auf Git für Windows verfügbar (zumindest für mich).
Andrew Keeton
104
Wenn Sie das Paket coreutils installiert haben, können Sie es im Allgemeinen verwenden, readlink -f relative_file_nameum das absolute Paket abzurufen (wobei alle Symlinks aufgelöst sind).
Das Verhalten hierfür unterscheidet sich ein wenig von dem, was der Benutzer verlangt. Es folgt und löst auch rekursive Symlinks an einer beliebigen Stelle im Pfad auf. In einigen Fällen möchten Sie das möglicherweise nicht.
Ffledgling
1
@BradPeabody Dies funktioniert auf einem Mac, wenn Sie Coreutils von Homebrew installieren brew install coreutils. Die ausführbare Datei wird jedoch von ag vorangestellt:greadlink -f relative_file_name
Miguel Isla
2
Beachten Sie, dass die Handbuchseite von readlink (1) als ersten Satz ihrer Beschreibung Folgendes enthält: "Beachten Sie, dass realpath (1) der bevorzugte Befehl für die Kanonisierungsfunktionalität ist."
Josch
1
Sie können -e anstelle von -f verwenden, um zu überprüfen, ob die Datei / das Verzeichnis vorhanden ist oder nicht
readlink ist die einfache Lösung für Linux, aber diese Lösung funktioniert auch unter OSX, also +1
thetoolman
1
Dieses Skript entspricht nicht dem, was realpathoder was zu readlink -ftun ist. Beispielsweise funktioniert es nicht auf Pfaden, bei denen die letzte Komponente ein Symlink ist.
Josch
2
@josch: Bei der Frage geht es nicht um das Auflösen von Symlinks. Aber wenn Sie das tun möchten, können Sie die -POption zum pwdBefehl bereitstellen :echo "$(cd "$(dirname "$1")"; pwd -P)/$(basename "$1")"
Eugen Konkov
4
Ich mag die Antwort, aber es funktioniert nur, wenn der Benutzer in das Verzeichnis cd darf. Dies ist möglicherweise nicht immer möglich.
Matthias B
34
Für das, was es wert ist, habe ich für die Antwort gestimmt, die ausgewählt wurde, wollte aber eine Lösung teilen. Der Nachteil ist, dass es nur Linux ist - ich habe ungefähr 5 Minuten lang versucht, das OSX-Äquivalent zu finden, bevor ich zum Stack-Überlauf kam. Ich bin mir aber sicher, dass es da draußen ist.
Unter Linux können Sie readlink -ezusammen mit verwenden dirname.
$(dirname $(readlink -e ../../../../etc/passwd))
ergibt
/etc/
Und dann benutzt du die dirnameSchwester, basenameum nur den Dateinamen zu bekommen
Ausgezeichnete Eintrag mit dirname, readlinkund basename. Das hat mir geholfen, den absoluten Weg einer symbolischen Verbindung zu finden - nicht ihr Ziel.
Kevinarpe
Funktioniert nicht, wenn Sie den Pfad zu symbolischen Links zurückgeben möchten (was ich zufällig tun muss ...).
Tomáš Zato - Wiedereinsetzung Monica
Wie könnten Sie jemals den absoluten Weg zu einem Weg finden, den es nicht gibt?
Synthesizerpatel
@synthesizerpatel Ganz einfach, hätte ich gedacht; wenn ich in bin /home/GKFXund ich gebe touch newfile, dann , bevor ich die Eingabetaste drücken könnten Sie arbeiten heraus , dass ich meine „create / home / GKFX / newfile“, die ein absoluter Pfad zu einer Datei, die noch nicht existiert.
GKFX
25
Ich denke, das ist das tragbarste:
abspath(){
cd "$(dirname "$1")"
printf "%s/%s\n""$(pwd)""$(basename "$1")"
cd "$OLDPWD"}
Es schlägt jedoch fehl, wenn der Pfad nicht vorhanden ist.
Es ist nicht nötig, erneut eine CD zu erstellen. Siehe stackoverflow.com/a/21188136/1504556 . Ihre ist die beste Antwort auf dieser Seite, IMHO. Für Interessenten gibt der Link eine Erklärung, warum diese Lösung funktioniert.
Peterh
Dies ist nicht sehr portabel, dirnameist ein GNU-Kerndienstprogramm, das meiner Meinung nach nicht allen Unixen gemeinsam ist.
Oh mein Gott, danke. Ich habe versucht, die Version zu reparieren, die ${1##*/}seit einem Tag verwendet wird, und jetzt, wo ich diesen Papierkorb durch basename "$1"ihn ersetzt habe, scheint es endlich richtig zu sein, Pfade zu behandeln, die mit / enden.
l3l_aze
NB, das macht nicht das Richtige mit einem Pfad, der in endet../..
Alex Coventry
16
realpath ist wahrscheinlich am besten
Aber ...
Die anfängliche Frage war anfangs sehr verwirrt, mit einem Beispiel, das, wie angegeben, schlecht mit der Frage zusammenhängt.
Die ausgewählte Antwort beantwortet tatsächlich das gegebene Beispiel und überhaupt nicht die Frage im Titel. Der erste Befehl ist diese Antwort (ist es wirklich? Ich bezweifle) und könnte auch ohne das '/' auskommen. Und ich sehe nicht, was der zweite Befehl tut.
Mehrere Themen sind gemischt:
Ändern eines relativen Pfadnamens in einen absoluten, was auch immer es bedeutet, möglicherweise nichts. (In der Regel, wenn Sie einen Befehl wie ztouch foo/bar , foo/barmuss der Pfadname für Sie vorhanden sein und möglicherweise für die Berechnung verwendet werden, bevor die Datei tatsächlich erstellt wird. )
Es kann mehrere absolute Pfadnamen geben, die dieselbe Datei (oder potenzielle Datei) bezeichnen, insbesondere aufgrund symbolischer Links (Symlinks) auf dem Pfad, möglicherweise jedoch aus anderen Gründen (ein Gerät kann doppelt als schreibgeschützt bereitgestellt werden). Man kann solche Symlinks explizit auflösen oder nicht.
Erreichen des Endes einer Kette symbolischer Links zu einer Datei oder einem Namen ohne Symlink. Dies kann einen absoluten Pfadnamen ergeben oder nicht, abhängig davon, wie es gemacht wird. Und man kann es in einen absoluten Pfadnamen auflösen oder nicht.
Der Befehl readlink foo ohne Option gibt nur dann eine Antwort, wenn sein Argument fooein symbolischer Link ist und diese Antwort der Wert dieses Symlinks ist. Es wird kein anderer Link verfolgt. Die Antwort kann ein relativer Pfad sein: Was auch immer der Wert des Symlink-Arguments war.
Jedoch, readlinkVerfügt über Optionen (-f -e oder -m), die für alle Dateien funktionieren, und gibt der Datei, die tatsächlich durch das Argument gekennzeichnet ist, einen absoluten Pfadnamen (den ohne Symlinks).
Dies funktioniert gut für alles, was kein Symlink ist, obwohl man möglicherweise einen absoluten Pfadnamen verwenden möchte, ohne die Zwischensymlinks auf dem Pfad aufzulösen. Dies erfolgt durch den Befehlrealpath -s foo
Im Fall eines Symlink-Arguments werden readlinkmit seinen Optionen wieder alle Symlinks auf dem absoluten Pfad zum Argument aufgelöst, aber dies schließt auch alle Symlinks ein, die auftreten können, wenn Sie dem Argumentwert folgen. Möglicherweise möchten Sie dies nicht, wenn Sie einen absoluten Pfad zum Argument symlink selbst wünschen, und nicht zu dem, mit dem es verknüpft ist. Auch wenn if fooein Symlink ist,realpath -s foo wird ein absoluter Pfad ohne Auflösen von Symlinks erhalten, einschließlich des als Argument angegebenen.
Ohne die -sOption realpathfunktioniert dies ziemlich genau so
readlink, außer dass nur der Wert eines Links und einige andere Dinge gelesen werden. Mir ist einfach nicht klar, warum readlinkes seine Optionen gibt, was anscheinend zu einer unerwünschten Redundanz führt
realpath .
Das Erkunden des Webs sagt nicht viel mehr aus, außer dass es einige Unterschiede zwischen den Systemen geben kann.
Fazit: realpathist der beste Befehl mit der größten Flexibilität, zumindest für die hier angeforderte Verwendung.
Meine Lieblingslösung war die von @EugenKonkov, da dies nicht die Anwesenheit anderer Dienstprogramme (das Coreutils-Paket) implizierte.
Aber es ist für die relativen Pfade "fehlgeschlagen." und "..", daher hier eine leicht verbesserte Version, die diese Sonderfälle behandelt.
Es schlägt jedoch immer noch fehl, wenn der Benutzer nicht über die Berechtigung verfügt, cdin das übergeordnete Verzeichnis des relativen Pfads zu wechseln.
#! /bin/sh# Takes a path argument and returns it as an absolute path. # No-op if the path is already absolute.function to-abs-path {local target="$1"if["$target"=="."];then
echo "$(pwd)"elif["$target"==".."];then
echo "$(dirname "$(pwd)")"else
echo "$(cd "$(dirname "$1")"; pwd)/$(basename "$1")"fi}
Wenn Sie Bash unter Mac OS X verwenden, bei dem weder ein Realpath vorhanden ist noch der Readlink den absoluten Pfad drucken kann, haben Sie möglicherweise die Wahl, Ihre eigene Version zu codieren, um ihn zu drucken. Hier ist meine Implementierung:
(reine Bash)
abspath(){local thePath
if[[!"$1"=~^/]];then
thePath="$PWD/$1"else
thePath="$1"fi
echo "$thePath"|(
IFS=/
read -a parr
declare -a outp
for i in"${parr[@]}";docase"$i"in''|.)continue;;..)
len=${#outp[@]}if((len==0));thencontinueelse
unset outp[$((len-1))]fi;;*)
len=${#outp[@]}
outp[$len]="$i";;esacdone
echo /"${outp[*]}")}
(benutze gawk)
abspath_gawk(){if[[-n "$1"]];then
echo $1|gawk '{
if(substr($0,1,1) != "/"){
path = ENVIRON["PWD"]"/"$0
} else path = $0
split(path, a, "/")
n = asorti(a, b,"@ind_num_asc")
for(i in a){
if(a[i]=="" || a[i]=="."){
delete a[i]
}
}
n = asorti(a, b, "@ind_num_asc")
m = 0
while(m!=n){
m = n
for(i=1;i<=n;i++){
if(a[b[i]]==".."){
if(b[i-1] in a){
delete a[b[i-1]]
delete a[b[i]]
n = asorti(a, b, "@ind_num_asc")
break
} else exit 1
}
}
}
n = asorti(a, b, "@ind_num_asc")
if(n==0){
printf "/"
} else {
for(i=1;i<=n;i++){
printf "/"a[b[i]]
}
}
}'fi}
Ähnlich wie bei der Antwort von @ ernest-a, aber ohne $OLDPWDeine neue Funktion zu beeinflussen oder zu definieren, können Sie eine Subshell auslösen(cd <path>; pwd)
$ pwd
/etc/apache2
$ cd ../cups
$ cd -/etc/apache2
$ (cd ~/..; pwd)/Users
$ cd -/etc/cups
Vielen Dank für dieses Code-Snippet, das möglicherweise nur begrenzte kurzfristige Hilfe bietet. Eine richtige Erklärung würde ihren langfristigen Wert erheblich verbessern, indem sie zeigt, warum dies eine gute Lösung für das Problem ist, und es für zukünftige Leser mit anderen, ähnlichen Fragen nützlicher machen. Bitte bearbeiten Sie Ihre Antwort, um eine Erklärung hinzuzufügen, einschließlich der von Ihnen getroffenen Annahmen.
Toby Speight
1
Eine Verbesserung der ziemlich schönen Version von @ ernest-a:
Dies behandelt den Fall korrekt, in dem das letzte Element des Pfades ist ... In diesem Fall wird die "$(pwd)/$(basename "$1")"Antwort von in @ ernest-a als durchkommen accurate_sub_path/spurious_subdirectory/...
Auf bash-4.3-p46 funktioniert dies nicht: Die Shell druckt eine leere Zeile, wenn ich laufedir=`cd ".."` && echo $dir
Michael
0
Dies ist eine verkettete Lösung von allen anderen, z. B. wenn ein realpathFehler auftritt, entweder weil sie nicht installiert ist oder weil sie mit Fehlercode beendet wird, wird die nächste Lösung versucht, bis der richtige Pfad gefunden wurde.
Ich konnte keine Lösung finden, die zwischen Mac OS Catalina, Ubuntu 16 und Centos 7 problemlos portierbar war. Daher habe ich mich für Python Inline entschieden und es funktionierte gut für meine Bash-Skripte.
Antworten:
verwenden:
um alle Dateien zu bekommen oder
um den vollständigen Pfad anzuzeigen (wenn der relative Pfad wichtig ist)
quelle
$(pwd)
anstelle von verwenden$PWD
? (Ja, ich weiß,pwd
ist ein eingebautes)Versuchen Sie es
realpath
.Verwenden Sie, um das Erweitern von Symlinks zu vermeiden
realpath -s
.Die Antwort kommt von " Befehl bash / fish, um den absoluten Pfad zu einer Datei zu drucken ".
quelle
realpath
scheint auf dem Mac nicht verfügbar zu sein (OS X 10.11 "El Capitan"). :-(realpath
scheint auch unter CentOS 6 nicht verfügbar zu seinbrew install coreutils
wird inrealpath
realpath
ist schon vorhanden. Ich musste es nicht separat installieren.realpath
ist es auf Git für Windows verfügbar (zumindest für mich).Wenn Sie das Paket coreutils installiert haben, können Sie es im Allgemeinen verwenden,
readlink -f relative_file_name
um das absolute Paket abzurufen (wobei alle Symlinks aufgelöst sind).quelle
brew install coreutils
. Die ausführbare Datei wird jedoch von ag vorangestellt:greadlink -f relative_file_name
UPD Einige Erklärungen
"$1"
dirname "$1"
cd "$(dirname "$1")
in dieses relative Verzeichnis und erhalten den absoluten Pfad dafür, indem wir denpwd
Shell-Befehl ausführen$(basename "$1")
echo
es geschafftquelle
realpath
oder was zureadlink -f
tun ist. Beispielsweise funktioniert es nicht auf Pfaden, bei denen die letzte Komponente ein Symlink ist.-P
Option zumpwd
Befehl bereitstellen :echo "$(cd "$(dirname "$1")"; pwd -P)/$(basename "$1")"
Für das, was es wert ist, habe ich für die Antwort gestimmt, die ausgewählt wurde, wollte aber eine Lösung teilen. Der Nachteil ist, dass es nur Linux ist - ich habe ungefähr 5 Minuten lang versucht, das OSX-Äquivalent zu finden, bevor ich zum Stack-Überlauf kam. Ich bin mir aber sicher, dass es da draußen ist.
Unter Linux können Sie
readlink -e
zusammen mit verwendendirname
.ergibt
Und dann benutzt du die
dirname
Schwester,basename
um nur den Dateinamen zu bekommenergibt
Alles zusammen ..
ergibt
Sie sind sicher, wenn Sie auf ein Verzeichnis abzielen,
basename
nichts zurückgeben und in der endgültigen Ausgabe nur doppelte Schrägstriche erhalten.quelle
dirname
,readlink
undbasename
. Das hat mir geholfen, den absoluten Weg einer symbolischen Verbindung zu finden - nicht ihr Ziel./home/GKFX
und ich gebetouch newfile
, dann , bevor ich die Eingabetaste drücken könnten Sie arbeiten heraus , dass ich meine „create / home / GKFX / newfile“, die ein absoluter Pfad zu einer Datei, die noch nicht existiert.Ich denke, das ist das tragbarste:
Es schlägt jedoch fehl, wenn der Pfad nicht vorhanden ist.
quelle
dirname
ist ein GNU-Kerndienstprogramm, das meiner Meinung nach nicht allen Unixen gemeinsam ist.dirname
ist ein POSIX-Standarddienstprogramm, siehe hier: pubs.opengroup.org/onlinepubs/9699919799/utilities/dirname.html${1##*/}
seit einem Tag verwendet wird, und jetzt, wo ich diesen Papierkorb durchbasename "$1"
ihn ersetzt habe, scheint es endlich richtig zu sein, Pfade zu behandeln, die mit / enden.../..
realpath
ist wahrscheinlich am bestenAber ...
Die anfängliche Frage war anfangs sehr verwirrt, mit einem Beispiel, das, wie angegeben, schlecht mit der Frage zusammenhängt.
Die ausgewählte Antwort beantwortet tatsächlich das gegebene Beispiel und überhaupt nicht die Frage im Titel. Der erste Befehl ist diese Antwort (ist es wirklich? Ich bezweifle) und könnte auch ohne das '/' auskommen. Und ich sehe nicht, was der zweite Befehl tut.
Mehrere Themen sind gemischt:
Ändern eines relativen Pfadnamens in einen absoluten, was auch immer es bedeutet, möglicherweise nichts. (In der Regel, wenn Sie einen Befehl wie z
touch foo/bar
,foo/bar
muss der Pfadname für Sie vorhanden sein und möglicherweise für die Berechnung verwendet werden, bevor die Datei tatsächlich erstellt wird. )Es kann mehrere absolute Pfadnamen geben, die dieselbe Datei (oder potenzielle Datei) bezeichnen, insbesondere aufgrund symbolischer Links (Symlinks) auf dem Pfad, möglicherweise jedoch aus anderen Gründen (ein Gerät kann doppelt als schreibgeschützt bereitgestellt werden). Man kann solche Symlinks explizit auflösen oder nicht.
Erreichen des Endes einer Kette symbolischer Links zu einer Datei oder einem Namen ohne Symlink. Dies kann einen absoluten Pfadnamen ergeben oder nicht, abhängig davon, wie es gemacht wird. Und man kann es in einen absoluten Pfadnamen auflösen oder nicht.
Der Befehl
readlink foo
ohne Option gibt nur dann eine Antwort, wenn sein Argumentfoo
ein symbolischer Link ist und diese Antwort der Wert dieses Symlinks ist. Es wird kein anderer Link verfolgt. Die Antwort kann ein relativer Pfad sein: Was auch immer der Wert des Symlink-Arguments war.Jedoch,
readlink
Verfügt über Optionen (-f -e oder -m), die für alle Dateien funktionieren, und gibt der Datei, die tatsächlich durch das Argument gekennzeichnet ist, einen absoluten Pfadnamen (den ohne Symlinks).Dies funktioniert gut für alles, was kein Symlink ist, obwohl man möglicherweise einen absoluten Pfadnamen verwenden möchte, ohne die Zwischensymlinks auf dem Pfad aufzulösen. Dies erfolgt durch den Befehl
realpath -s foo
Im Fall eines Symlink-Arguments werden
readlink
mit seinen Optionen wieder alle Symlinks auf dem absoluten Pfad zum Argument aufgelöst, aber dies schließt auch alle Symlinks ein, die auftreten können, wenn Sie dem Argumentwert folgen. Möglicherweise möchten Sie dies nicht, wenn Sie einen absoluten Pfad zum Argument symlink selbst wünschen, und nicht zu dem, mit dem es verknüpft ist. Auch wenn iffoo
ein Symlink ist,realpath -s foo
wird ein absoluter Pfad ohne Auflösen von Symlinks erhalten, einschließlich des als Argument angegebenen.Ohne die
-s
Optionrealpath
funktioniert dies ziemlich genau soreadlink
, außer dass nur der Wert eines Links und einige andere Dinge gelesen werden. Mir ist einfach nicht klar, warumreadlink
es seine Optionen gibt, was anscheinend zu einer unerwünschten Redundanz führtrealpath
.Das Erkunden des Webs sagt nicht viel mehr aus, außer dass es einige Unterschiede zwischen den Systemen geben kann.
Fazit:
realpath
ist der beste Befehl mit der größten Flexibilität, zumindest für die hier angeforderte Verwendung.quelle
Meine Lieblingslösung war die von @EugenKonkov, da dies nicht die Anwesenheit anderer Dienstprogramme (das Coreutils-Paket) implizierte.
Aber es ist für die relativen Pfade "fehlgeschlagen." und "..", daher hier eine leicht verbesserte Version, die diese Sonderfälle behandelt.
Es schlägt jedoch immer noch fehl, wenn der Benutzer nicht über die Berechtigung verfügt,
cd
in das übergeordnete Verzeichnis des relativen Pfads zu wechseln.quelle
Eugens Antwort hat bei mir nicht ganz funktioniert, aber das hat funktioniert:
Nebenbei bemerkt, Ihr aktuelles Arbeitsverzeichnis ist nicht betroffen.
quelle
Die beste Lösung, imho, ist die hier veröffentlichte: https://stackoverflow.com/a/3373298/9724628 .
Es erfordert Python, um zu funktionieren, aber es scheint alle oder die meisten Randfälle abzudecken und eine sehr tragbare Lösung zu sein.
quelle
Im Falle von
find
ist es wahrscheinlich am einfachsten, nur den absoluten Pfad für die Suche anzugeben, z.quelle
Wenn Sie Bash unter Mac OS X verwenden, bei dem weder ein Realpath vorhanden ist noch der Readlink den absoluten Pfad drucken kann, haben Sie möglicherweise die Wahl, Ihre eigene Version zu codieren, um ihn zu drucken. Hier ist meine Implementierung:
(reine Bash)
(benutze gawk)
(pure bsd awk)
Beispiel:
quelle
Was sie sagten, außer
find $PWD
oder (in Bash)find ~+
ist ein bisschen bequemer.quelle
Ähnlich wie bei der Antwort von @ ernest-a, aber ohne
$OLDPWD
eine neue Funktion zu beeinflussen oder zu definieren, können Sie eine Subshell auslösen(cd <path>; pwd)
quelle
Wenn der relative Pfad ein Verzeichnispfad ist, versuchen Sie meinen, sollte der beste sein:
quelle
quelle
Eine Verbesserung der ziemlich schönen Version von @ ernest-a:
Dies behandelt den Fall korrekt, in dem das letzte Element des Pfades ist
..
. In diesem Fall wird die"$(pwd)/$(basename "$1")"
Antwort von in @ ernest-a als durchkommenaccurate_sub_path/spurious_subdirectory/..
.quelle
Wenn Sie eine Variable mit einem relativen Pfad in einen absoluten Pfad umwandeln möchten, funktioniert dies wie folgt:
"cd" hallt wider, ohne das Arbeitsverzeichnis zu ändern, da es hier in einer Sub-Shell ausgeführt wird.
quelle
dir=`cd ".."` && echo $dir
Dies ist eine verkettete Lösung von allen anderen, z. B. wenn ein
realpath
Fehler auftritt, entweder weil sie nicht installiert ist oder weil sie mit Fehlercode beendet wird, wird die nächste Lösung versucht, bis der richtige Pfad gefunden wurde.quelle
Sie können die Bash-String-Ersetzung für jeden relativen Pfad $ line verwenden:
Die grundlegende Front-of-String-Ersetzung folgt der Formel
$ {string / # substring / replace},
die hier ausführlich erläutert wird: https://www.tldp.org/LDP/abs/html/string-manipulation.html
Das
\
Zeichen negiert das,/
wenn es Teil der Zeichenfolge sein soll, die wir finden / ersetzen.quelle
Ich konnte keine Lösung finden, die zwischen Mac OS Catalina, Ubuntu 16 und Centos 7 problemlos portierbar war. Daher habe ich mich für Python Inline entschieden und es funktionierte gut für meine Bash-Skripte.
quelle