Answers:
您可以使用该readlink
实用程序,并提供以下-f
选项:
-f, --canonicalize
canonicalize by following every symlink in every component of the given name recursively; all but the last component must exist
某些发行版,例如使用GNU coreutils和FreeBSD的发行版,还附带了一个realpath(1)
实用程序,该实用程序基本上只调用realpath(3)
并执行几乎相同的操作。
readlink
也不提供realpath
,尤其是Solaris和HP-UX。
brew install coreutils
apple.stackexchange.com/a/69332/23040,如果您不想执行将所有标准Mac CLI工具重定向到新安装的GNU等效项的步骤,请致电greadlink
。
可移植地,该PWD
变量由外壳程序设置为当前目录的一个绝对位置。该路径的任何组件都可以是符号链接。
case $f in
/*) absolute=$f;;
*) absolute=$PWD/$f;;
esac
如果你想消除.
和..
也,切换到该目录包含文件,并获得$PWD
有:
if [ -d "$f" ]; then f=$f/.; fi
absolute=$(cd "$(dirname -- "$f")"; printf %s. "$PWD")
absolute=${absolute%?}
absolute=$absolute/${f##*/}
没有跟随符号链接的便携式方法。如果您有目录的路径,那么大多数unices会$(cd -- "$dir" && pwd -P 2>/dev/null || pwd)
提供不使用符号链接的路径,因为跟踪符号链接的shell易于实现pwd -P
(“ P”表示“物理”)。
某些unices提供实用程序来打印文件的“物理”路径。
readlink -f
FreeBSD≥8.3,NetBSD≥4.0和OpenBSD早于2.2。realpath
(它在某些Linux系统上也存在,并且在BusyBox中)。如果有Perl,则可以使用Cwd
模块。
perl -MCwd -e 'print Cwd::realpath($ARGV[0])' path/to/file
pwd
($(cd -- "$dir" && pwd -P 2>/dev/null | pwd)
)?似乎并不在乎stdin。
||
是否pwd
适合您的需求?它给出了当前目录的绝对路径。或者,您想要的是realpath()。
alister
并rss67
在本文中介绍最稳定,兼容和最简单的方法。我从未见过比这更好的方法。
RELPATH=./../
cd $RELPATH
ABSPATH=`pwd`
如果您想返回原始位置,
ORGPATH=`pwd`
RELPATH=./../
cd $RELPATH
ABSPATH=`pwd`
cd $ORGPATH
要么
RELPATH=./../
cd $RELPATH
ABSPATH=`pwd`
cd -
我希望这会有所帮助。这对我来说是最大的解决方案。
ABSPATH=$(cd -- "$RELPATH" && pwd)
。请注意替换处的双引号(以便在路径包含空格和通配符的--
情况下不会引起折断)和(在路径以开头的情况下-
)。同样,这仅适用于目录,并且不能按要求规范化符号链接。请参阅我的答案以获取更多详细信息。
这里的其他答案很好,但不足以满足我的需求。我需要一个可以在任何计算机上的脚本中使用的解决方案。我的解决方案是编写一个Shell脚本,可以从需要的脚本中调用它。
#!/bin/sh
if [ $# -eq 0 ] || [ $# -gt 2 ]; then
printf 'Usage: respath path [working-directory]\n' >&2
exit 1
fi
cantGoUp=
path=$1
if [ $# -gt 1 ]; then
cd "$2"
fi
cwd=`pwd -P` #Use -P option to account for directories that are actually symlinks
#Handle non-relative paths, which don't need resolution
if echo "$path" | grep '^/' > /dev/null ; then
printf '%s\n' "$path"
exit 0
fi
#Resolve for each occurrence of ".." at the beginning of the given path.
#For performance, don't worry about ".." in the middle of the path.
while true
do
case "$path" in
..*)
if [ "$cwd" = '/' ]; then
printf 'Invalid relative path\n' >&2
exit 1
fi
if [ "$path" = '..' ]; then
path=
else
path=`echo "$path" | sed 's;^\.\./;;'`
fi
cwd=`dirname $cwd`
;;
*)
break
;;
esac
done
cwd=`echo "$cwd" | sed 's;/$;;'`
if [ -z "$path" ]; then
if [ -z "$cwd" ]; then
cwd='/'
fi
printf '%s\n' "$cwd"
else
printf '%s/%s\n' "$cwd" "$path"
fi
此解决方案是为Bourne Shell编写的,以实现可移植性。我在名为“ respath.sh”的脚本中拥有此文件。
该脚本可以这样使用:
respath.sh '/path/to/file'
或者像这样
respath.sh '/relative/path/here' '/path/to/resolve/relative/to'
该脚本使用第二个自变量的路径作为起点来解析第一个自变量的路径。如果仅提供第一个参数,则脚本将解析相对于当前工作目录的路径。
pwd
内置,不支持-P
(Bourne shell的未实施该逻辑$ PWD处理像POSIX壳做)。
cd -P --
以及万一第一个参数包含了一些..
case
支票应..|../*)
改为..*
。
dirname $cwd
假设变量a存储路径名(a =“ whatever”)
1.对于潜在的空间路径:
c=$(grep -o " " <<< $a | wc -l); if (( $c > "0" )); then a=$(sed 's/ /\\ /g' <<< $a); fi
2.对于实际问题,即将路径转换为绝对值:readlink可以检索符号链接的内容,可以按以下方式使用。(注意readlink -f
本来可以是完美的,但是至少在Mac OS X bash中不可用,其中-f代表FORMATS。)
if [[ $(readlink $a) == "" ]]; then a=$(cd $a; pwd); else a=$(cd $(readlink $a); pwd); fi
3.刚学到pwd -P
的man pwd
:-P是为“ 显示物理当前工作目录(所有符号链接解决) ”,因此
if (( $(grep -o " " <<< $a | wc -l) > "0" )); then a=$(sed 's/ /\\ /g' <<< $a); fi; a=$(cd $a; pwd -P)
也会工作。
结论:将1与2结合起来可以满足您的两个需求,而包含空格的路径名已经在更简洁的3中得到了考虑。
-f
开关在Mac OS X上不存在(至少从10.8.5开始)。如果没有该-f
开关,它将仅返回错误代码。