Als Argumente für mein Skript gibt es einige Dateipfade. Diese können natürlich relativ sein (oder ~ enthalten). Aber für die Funktionen, die ich geschrieben habe, brauche ich Pfade, die absolut sind, deren Symlinks jedoch nicht aufgelöst sind.
Gibt es dafür eine Funktion?
linux
bash
absolute-path
laar
quelle
quelle
readlink
löst Symlinks auf; Das OP will das nicht.echo $(cd some_directory && pwd)
, Symlink nicht auflösen, schlägt fehl, wenn some_directory nicht vorhanden ist. Arbeitsverzeichnis nicht betroffen. oder einer Variablen zuweisenMY_PATH=$(cd some_directory && pwd)
.Antworten:
MY_PATH=$(readlink -f $YOUR_ARG)
löst relative Pfade wie"./"
und auf"../"
Beachten Sie auch dies ( Quelle ):
#!/bin/bash dir_resolve() { cd "$1" 2>/dev/null || return $? # cd to desired directory; if fail, quell any error messages but return exit status echo "`pwd -P`" # output full, link-resolved path } # sample usage if abs_path="`dir_resolve \"$1\"`" then echo "$1 resolves to $abs_path" echo pwd: `pwd` # function forks subshell, so working directory outside function is not affected else echo "Could not reach $1" fi
quelle
man pwd
: "-P Zeigt das physische aktuelle Arbeitsverzeichnis an (alle symbolischen Links wurden aufgelöst)", entfernen Sie einfach das-P
readlink -f
Funktionalität unter OS X zu erhalten, können Sie Homebrew verwenden und dann ausführen:$ brew install coreutils
Sie können dann verwendengreadlink -f
.http://www.linuxquestions.org/questions/programming-9/bash-script-return-full-path-and-filename-680368/page3.html hat Folgendes
function abspath { if [[ -d "$1" ]] then pushd "$1" >/dev/null pwd popd >/dev/null elif [[ -e "$1" ]] then pushd "$(dirname "$1")" >/dev/null echo "$(pwd)/$(basename "$1")" popd >/dev/null else echo "$1" does not exist! >&2 return 127 fi }
welches
pushd
/ benutztpopd
, um in einen Zustand zu gelangen, in dempwd
es nützlich ist.quelle
DIRSTACK
und sonst nichts. Schöne Lösung!sh
,pushd; cd <dir>; <cmd>; popd
kann durch ersetzt werden(cd <dir>; <cmd>)
.Einfacher Einzeiler:
function abs_path { (cd "$(dirname '$1')" &>/dev/null && printf "%s/%s" "$PWD" "${1##*/}") }
Verwendung:
function do_something { local file=$(abs_path $1) printf "Absolute path to %s: %s\n" "$1" "$file" } do_something $HOME/path/to/some\ where
Ich versuche immer noch herauszufinden, wie ich dafür sorgen kann, dass ich nicht weiß, ob der Pfad existiert oder nicht (daher kann er auch beim Erstellen von Dateien verwendet werden).
quelle
cd -
später zurücksetzen?${1##*/}
mitbasename
allerdings ohne es in einer separaten Variable zu setzen, Pfade mit Leerzeichen nicht richtig funktionieren.$PWD
Dies macht den Trick für mich unter OS X:
$(cd SOME_DIRECTORY 2> /dev/null && pwd -P)
Es sollte überall funktionieren. Die anderen Lösungen schienen zu kompliziert.
quelle
unter OS X können Sie verwenden
stat -f "%N" YOUR_PATH
Unter Linux haben Sie möglicherweise eine
realpath
ausführbare Datei. Andernfalls funktioniert möglicherweise Folgendes (nicht nur für Links):quelle
stat -f "%N" PATH
gibt mir genau den gleichen Weg, den ich ihm gegeben habe.Verwenden Sie
readlink -f <relative-path>
zexport FULLPATH=`readlink -f ./`
quelle
Möglicherweise ist dies besser lesbar und verwendet keine Unterschale und ändert das aktuelle Verzeichnis nicht:
dir_resolve() { local dir=`dirname "$1"` local file=`basename "$1"` pushd "$dir" &>/dev/null || return $? # On error, return error code echo "`pwd -P`/$file" # output full, link-resolved path with filename popd &> /dev/null }
quelle
Es gibt noch eine andere Methode. Sie können die Python-Einbettung in ein Bash-Skript verwenden, um einen relativen Pfad aufzulösen.
abs_path=$(python3 - <<END from pathlib import Path path = str(Path("$1").expanduser().resolve()) print(path) END )
quelle
Selbstbearbeitung, ich habe gerade bemerkt, dass das OP sagte, er suche nicht nach gelösten Symlinks:
"Aber für die Funktionen, die ich geschrieben habe, brauche ich Pfade, die absolut sind, deren Symlinks jedoch nicht aufgelöst sind."
Vermutlich ist das doch nicht so passend für seine Frage. :) :)
Da ich im Laufe der Jahre oft darauf gestoßen bin und dieses Mal eine reine Bash-Portable-Version brauchte, die ich unter OSX und Linux verwenden konnte, schrieb ich eine:
Die lebende Version lebt hier:
https://github.com/keen99/shell-functions/tree/master/resolve_path
Aber um SO willen, hier ist die aktuelle Version (ich denke, sie ist gut getestet. Aber ich bin offen für Feedback!)
Es könnte nicht schwierig sein, es für eine einfache Bourne-Shell (sh) zum Laufen zu bringen, aber ich habe es nicht versucht ... Ich mag $ FUNCNAME zu sehr. :) :)
#!/bin/bash resolve_path() { #I'm bash only, please! # usage: resolve_path <a file or directory> # follows symlinks and relative paths, returns a full real path # local owd="$PWD" #echo "$FUNCNAME for $1" >&2 local opath="$1" local npath="" local obase=$(basename "$opath") local odir=$(dirname "$opath") if [[ -L "$opath" ]] then #it's a link. #file or directory, we want to cd into it's dir cd $odir #then extract where the link points. npath=$(readlink "$obase") #have to -L BEFORE we -f, because -f includes -L :( if [[ -L $npath ]] then #the link points to another symlink, so go follow that. resolve_path "$npath" #and finish out early, we're done. return $? #done elif [[ -f $npath ]] #the link points to a file. then #get the dir for the new file nbase=$(basename $npath) npath=$(dirname $npath) cd "$npath" ndir=$(pwd -P) retval=0 #done elif [[ -d $npath ]] then #the link points to a directory. cd "$npath" ndir=$(pwd -P) retval=0 #done else echo "$FUNCNAME: ERROR: unknown condition inside link!!" >&2 echo "opath [[ $opath ]]" >&2 echo "npath [[ $npath ]]" >&2 return 1 fi else if ! [[ -e "$opath" ]] then echo "$FUNCNAME: $opath: No such file or directory" >&2 return 1 #and break early elif [[ -d "$opath" ]] then cd "$opath" ndir=$(pwd -P) retval=0 #done elif [[ -f "$opath" ]] then cd $odir ndir=$(pwd -P) nbase=$(basename "$opath") retval=0 #done else echo "$FUNCNAME: ERROR: unknown condition outside link!!" >&2 echo "opath [[ $opath ]]" >&2 return 1 fi fi #now assemble our output echo -n "$ndir" if [[ "x${nbase:=}" != "x" ]] then echo "/$nbase" else echo fi #now return to where we were cd "$owd" return $retval }
Hier ist ein klassisches Beispiel, dank Brew:
%% ls -l `which mvn` lrwxr-xr-x 1 draistrick 502 29 Dec 17 10:50 /usr/local/bin/mvn@ -> ../Cellar/maven/3.2.3/bin/mvn
Verwenden Sie diese Funktion und es wird der -real- Pfad zurückgegeben:
%% cat test.sh #!/bin/bash . resolve_path.inc echo echo "relative symlinked path:" which mvn echo echo "and the real path:" resolve_path `which mvn` %% test.sh relative symlinked path: /usr/local/bin/mvn and the real path: /usr/local/Cellar/maven/3.2.3/libexec/bin/mvn
quelle
Wenn Ihr Betriebssystem dies unterstützt, verwenden Sie:
realpath "./some/dir"
Und mit einer Variablen:
some_path="$(realpath "./some/dir")"
Welches wird Ihren Weg erweitern. Unter Ubuntu und CentOS getestet, ist es bei Ihnen möglicherweise nicht verfügbar. Einige empfehlen Readlink, aber die Dokumentation für Readlink lautet:
Falls sich die Leute fragen, warum ich meine Variablen zitiere, müssen Leerzeichen in Pfaden erhalten bleiben. Wenn Sie dies tun
realpath some path
, erhalten Sie zwei unterschiedliche Pfadergebnisse. Aberrealpath "some path"
ich werde einen zurückgeben. Zitierte Parameter ftw :)quelle
Müssen Sie ausschließlich Bash verwenden? Ich musste dies tun und hatte genug von Unterschieden zwischen Linux und OS X. Also benutzte ich PHP für eine schnelle und schmutzige Lösung.
#!/usr/bin/php <-- or wherever <?php { if($argc!=2) exit(); $fname=$argv[1]; if(!file_exists($fname)) exit(); echo realpath($fname)."\n"; } ?>
Ich weiß, dass es keine sehr elegante Lösung ist, aber es funktioniert.
quelle