我有一个Bash脚本需要知道它的完整路径.我试图找到一种广泛兼容的方式来做到这一点,而不会结束相对或时髦的路径.我只需要支持Bash,而不是sh,csh等.
到目前为止我发现了什么:
从地址中获取Bash脚本的源目录的接受答案是获取脚本的路径dirname $0,这很好,但可能会返回相对路径(如.),如果要更改目录中的目录,这是一个问题脚本并使路径仍指向脚本的目录.不过,dirname将成为这个难题的一部分.
对OS X的Bash脚本绝对路径 的接受答案(特定于OS X,但答案无论如何)都会给出一个函数,该函数将测试是否$0看起来相对,如果是,则会预先挂起$PWD.但是结果仍然可以包含相对位(虽然总体来说它是绝对的) - 例如,如果脚本t在目录中/usr/bin并且你进入/usr并且你输入bin/../bin/t它来运行它(是的,那是复杂的),你最终会得到/usr/bin/../binas脚本的目录路径.哪个有效,但......
此页面上的readlink解决方案如下所示:
# Absolute path to this script. /home/user/bin/foo.sh
SCRIPT=$(readlink -f $0)
# Absolute path this script is in. /home/user/bin
SCRIPTPATH=`dirname $SCRIPT`
Run Code Online (Sandbox Code Playgroud)
但是readlink不是POSIX,显然解决方案依赖于GNU readlink,其中BSD由于某种原因无法工作(我无法访问类似BSD的系统进行检查).
所以,各种方式,但他们都有他们的警告.
什么是更好的方式?"更好"的意思是:
T.J*_*der 541
以下是我的想法(编辑:加上sfstewman,levigroker,Kyle Strand和Rob Kennedy提供的一些调整),这似乎最符合我的"更好"标准:
SCRIPTPATH="$( cd "$(dirname "$0")" ; pwd -P )"
Run Code Online (Sandbox Code Playgroud)
这SCRIPTPATH条线似乎特别迂回,但我们需要它而不是SCRIPTPATH=`pwd`为了正确处理空格和符号链接.
还要注意,深奥的情况,例如执行一个完全不可能来自可访问文件系统中的文件的脚本(这是完全可能的),不能满足那里(或者我见过的任何其他答案) ).
Dar*_*tle 209
我很惊讶realpath这里没有提到这个命令.我的理解是它广泛便携/移植.
您的初始解决方案变为
SCRIPT=`realpath $0`
SCRIPTPATH=`dirname $SCRIPT`
Run Code Online (Sandbox Code Playgroud)
并根据您的偏好保留未解析的符号链接:
SCRIPT=`realpath -s $0`
SCRIPTPATH=`dirname $SCRIPT`
Run Code Online (Sandbox Code Playgroud)
小智 168
我发现在Bash中获得完整规范路径的最简单方法是使用cd和pwd:
ABSOLUTE_PATH="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/$(basename "${BASH_SOURCE[0]}")"
Run Code Online (Sandbox Code Playgroud)
使用${BASH_SOURCE[0]},而不是$0不管脚本是否被调用为产生相同的行为<name>或source <name>.
Fel*_*abe 49
我今天不得不重新审视这个问题,并发现从内部获取Bash脚本的源目录.它详细阐述了我过去使用过的解决方案.
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
Run Code Online (Sandbox Code Playgroud)
链接答案中有更多变体,例如脚本本身是符号链接的情况.
Gre*_*Fox 37
它不使用-freadlink中的选项,因此它应该适用于BSD/Mac OS X.
.点运算符调用时)foo->dir1/dir2/bar bar->./../doe doe->script我正在寻找此代码不起作用的极端情况.请告诉我.
pushd . > /dev/null
SCRIPT_PATH="${BASH_SOURCE[0]}";
while([ -h "${SCRIPT_PATH}" ]); do
cd "`dirname "${SCRIPT_PATH}"`"
SCRIPT_PATH="$(readlink "`basename "${SCRIPT_PATH}"`")";
done
cd "`dirname "${SCRIPT_PATH}"`" > /dev/null
SCRIPT_PATH="`pwd`";
popd > /dev/null
echo "srcipt=[${SCRIPT_PATH}]"
echo "pwd =[`pwd`]"
Run Code Online (Sandbox Code Playgroud)
该脚本必须位于某个磁盘上.让它通过网络.如果您尝试从PIPE运行此脚本,它将无法正常工作
wget -o /dev/null -O - http://host.domain/dir/script.sh |bash
Run Code Online (Sandbox Code Playgroud)
从技术上讲,它是未定义的.实际上,没有理智的方法来检测这一点.(协同进程无法访问父进程的环境.)
Mat*_*att 33
使用:
SCRIPT_PATH=$(dirname `which $0`)
Run Code Online (Sandbox Code Playgroud)
which 打印到标准输出时,在shell提示符下输入传递的参数时将执行的可执行文件的完整路径(这是$ 0包含的内容)
dirname 从文件名中删除非目录后缀.
因此,无论路径是否被指定,您最终都会获得脚本的完整路径.
ypi*_*pid 24
由于我的Linux系统上没有默认安装realpath,以下内容适用于我:
SCRIPT="$(readlink --canonicalize-existing "$0")"
SCRIPTPATH="$(dirname "$SCRIPT")"
Run Code Online (Sandbox Code Playgroud)
$SCRIPT将包含脚本的实际文件路径以及$SCRIPTPATH包含脚本的目录的实际路径.
在使用之前阅读这个答案的评论.
ger*_*rdw 13
易于阅读?以下是另一种选择.它忽略了符号链接
#!/bin/bash
currentDir=$(
cd $(dirname "$0")
pwd
)
echo -n "current "
pwd
echo script $currentDir
Run Code Online (Sandbox Code Playgroud)
Sto*_*oud 10
很晚才回答这个问题,但我使用:
SCRIPT=$( readlink -m $( type -p $0 )) # Full path to script
BASE_DIR=`dirname ${SCRIPT}` # Directory script is run in
NAME=`basename ${SCRIPT}` # Actual name of script even if linked
Run Code Online (Sandbox Code Playgroud)
我们在GitHub上放置了我们自己的产品realpath-lib,用于免费和无阻碍的社区使用.
无耻的插件,但有了这个Bash库你可以:
get_realpath <absolute|relative|symlink|local file>
Run Code Online (Sandbox Code Playgroud)
这个函数是库的核心:
function get_realpath() {
if [[ -f "$1" ]]
then
# file *must* exist
if cd "$(echo "${1%/*}")" &>/dev/null
then
# file *may* not be local
# exception is ./file.ext
# try 'cd .; cd -;' *works!*
local tmppwd="$PWD"
cd - &>/dev/null
else
# file *must* be local
local tmppwd="$PWD"
fi
else
# file *cannot* exist
return 1 # failure
fi
# reassemble realpath
echo "$tmppwd"/"${1##*/}"
return 0 # success
}
Run Code Online (Sandbox Code Playgroud)
它不需要任何外部依赖,只需要Bash 4+.还包含了这些功能get_dirname,get_filename,get_stemname和validate_path validate_realpath.它是免费的,干净的,简单的,文档齐全的,因此它也可以用于学习目的,毫无疑问可以改进.跨平台尝试.
更新:经过一些审查和测试后,我们用一些实现相同结果的东西替换了上面的函数(不使用dirname,只有纯Bash),但效率更高:
function get_realpath() {
[[ ! -f "$1" ]] && return 1 # failure : file does not exist.
[[ -n "$no_symlinks" ]] && local pwdp='pwd -P' || local pwdp='pwd' # do symlinks.
echo "$( cd "$( echo "${1%/*}" )" 2>/dev/null; $pwdp )"/"${1##*/}" # echo result.
return 0 # success
}
Run Code Online (Sandbox Code Playgroud)
这还包括一个环境设置no_symlinks,可以将符号链接解析到物理系统.默认情况下,它保持符号链接不变.
您可以尝试定义以下变量:
CWD="$(cd -P -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd -P)"
Run Code Online (Sandbox Code Playgroud)
或者您可以在Bash中尝试以下功能:
realpath () {
[[ $1 = /* ]] && echo "$1" || echo "$PWD/${1#./}"
}
Run Code Online (Sandbox Code Playgroud)
这个函数有一个参数.如果参数已经有绝对路径,则按原样打印,否则打印$PWD变量+文件名参数(不带./前缀).
有关:
| 归档时间: |
|
| 查看次数: |
421009 次 |
| 最近记录: |