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, aber ihre Symlinks nicht aufgelöst haben.
Gibt es dafür eine Funktion?
MY_PATH=$(readlink -f $YOUR_ARG)
löst relative Pfade wie "./"
und "../"
auf
Betrachten Sie dies auch ( source ):
#!/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
http://www.linuxquestions.org/questions/programming-9/bash-script-return-full-path-und-dateiname-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
}
welche pushd
/popd
verwendet, um in einen Zustand zu gelangen, in dem pwd
nützlich ist.
Einfaches Liner:
function abs_path {
(cd "$(dirname '$1')" &>/dev/null && printf "%s/%s" "$PWD" "${1##*/}")
}
Verwendungszweck:
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 der Pfad überhaupt nicht beachtet wird (ob er vorhanden ist oder nicht) (er kann auch beim Erstellen von Dateien verwendet werden).
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 zu sein.
unter OS X können Sie verwenden
stat -f "%N" YOUR_PATH
unter Linux können Sie realpath
ausführbar sein. Wenn nicht, kann Folgendes funktionieren (nicht nur für Links):
readlink -c YOUR_PATH
Vielleicht ist dies besser lesbar und verwendet keine Subshell 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
}
Verwenden Sie readlink -f <relative-path>
, z.
export FULLPATH=`readlink -f ./`
Es gibt noch eine andere Methode. Sie können die Einbettung von python 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
)
selbstbearbeitung, ich habe gerade bemerkt, dass das OP sagte, er suche nicht nach aufgelösten Symlinks:
"Aber für die Funktionen, die ich geschrieben habe, brauche ich absolute Pfade, deren Symlinks jedoch nicht aufgelöst werden."
Also denke, das ist doch nicht so gut für seine Frage. :)
Da ich im Laufe der Jahre viele Male darauf gestoßen bin und diesmal eine reine bash portable Version brauchte, die ich unter OSX und Linux verwenden konnte, schrieb ich eine und schrieb eine:
Die lebende Version lebt hier:
https://github.com/keen99/Shell-functions/tree/master/resolve_path
aber um der Sache willen, hier ist die aktuelle Version (ich denke, es ist gut getestet ... aber ich bin offen für Rückmeldungen!)
Es könnte nicht schwer sein, es mit normaler Borne-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/[email protected] -> ../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