#!/bin/bash
# Absolute path to this script, e.g. /home/user/bin/foo.sh
SCRIPT=$(readlink -f "$0")
# Absolute path this script is in, thus /home/user/bin
SCRIPTPATH=$(dirname "$SCRIPT")
echo $SCRIPTPATH
对于tcsh,csh:
#!/bin/tcsh
# Absolute path to this script, e.g. /home/user/bin/foo.csh
set SCRIPT=`readlink -f "$0"`
# Absolute path this script is in, thus /home/user/bin
set SCRIPTPATH=`dirname "$SCRIPT"`
echo $SCRIPTPATH
#!/bin/bash
pushd $(dirname "${0}") > /dev/null
basedir=$(pwd -L)
# Use "pwd -P" for the path without links. man bash for more info.
popd > /dev/null
echo "${basedir}"
2
正如马科所说:
BASEDIR=$(dirname $0)
echo $BASEDIR
除非您从脚本所在的同一目录执行脚本,否则这将起作用,在这种情况下,您将获得值“ . ”
要解决该问题,请使用:
current_dir=$(pwd)
script_dir=$(dirname $0)
if [ $script_dir = '.' ]
then
script_dir="$current_dir"
fi
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
One-liner将为您提供脚本的完整目录名称,无论它在何处被调用 .
要了解它是如何工作的,您可以执行以下脚本:
#!/bin/bash
SOURCE="${BASH_SOURCE[0]}"
while [ -h "$SOURCE" ]; do # resolve $SOURCE until the file is no longer a symlink
TARGET="$(readlink "$SOURCE")"
if [[ $TARGET == /* ]]; then
echo "SOURCE '$SOURCE' is an absolute symlink to '$TARGET'"
SOURCE="$TARGET"
else
DIR="$( dirname "$SOURCE" )"
echo "SOURCE '$SOURCE' is a relative symlink to '$TARGET' (relative to '$DIR')"
SOURCE="$DIR/$TARGET" # if $SOURCE was a relative symlink, we need to resolve it relative to the path where the symlink file was located
fi
done
echo "SOURCE is '$SOURCE'"
RDIR="$( dirname "$SOURCE" )"
DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )"
if [ "$DIR" != "$RDIR" ]; then
echo "DIR '$RDIR' resolves to '$DIR'"
fi
echo "DIR is '$DIR'"
#!/bin/bash
#this script will only work in bash, make sure it's installed on your system.
#set to false to not see all the echos
debug=true
if [ "$debug" = true ]; then echo "\$0=$0";fi
#The line below detect script's parent directory. $0 is the part of the launch command that doesn't contain the arguments
BASEDIR=$(dirname "$0") #3 situations will cause dirname $0 to fail: #situation1: user launches script while in script dir ( $0=./script)
#situation2: different dir but ./ is used to launch script (ex. $0=/path_to/./script)
#situation3: different dir but relative path used to launch script
if [ "$debug" = true ]; then echo 'BASEDIR=$(dirname "$0") gives: '"$BASEDIR";fi
if [ "$BASEDIR" = "." ]; then BASEDIR="$(pwd)";fi # fix for situation1
_B2=${BASEDIR:$((${#BASEDIR}-2))}; B_=${BASEDIR::1}; B_2=${BASEDIR::2}; B_3=${BASEDIR::3} # <- bash only
if [ "$_B2" = "/." ]; then BASEDIR=${BASEDIR::$((${#BASEDIR}-1))};fi #fix for situation2 # <- bash only
if [ "$B_" != "/" ]; then #fix for situation3 #<- bash only
if [ "$B_2" = "./" ]; then
#covers ./relative_path/(./)script
if [ "$(pwd)" != "/" ]; then BASEDIR="$(pwd)/${BASEDIR:2}"; else BASEDIR="/${BASEDIR:2}";fi
else
#covers relative_path/(./)script and ../relative_path/(./)script, using ../relative_path fails if current path is a symbolic link
if [ "$(pwd)" != "/" ]; then BASEDIR="$(pwd)/$BASEDIR"; else BASEDIR="/$BASEDIR";fi
fi
fi
if [ "$debug" = true ]; then echo "fixed BASEDIR=$BASEDIR";fi
15 回答
之前对答案的评论说,但在所有其他答案中很容易错过 .
使用bash时:
Bash Reference Manual, 5.2 Bash Variables
原始帖子包含解决方案(忽略响应,他们不添加任何有用的东西) . 有趣的工作是通过提到的unix命令
readlink
和选项-f
来完成的 . 当脚本由绝对路径和相对路径调用时工作 .对于bash,sh,ksh:
对于tcsh,csh:
另见:https://stackoverflow.com/a/246128/59087
在Bash中,你应该得到你需要的东西:
假设你正在使用bash
此脚本应该打印您所在的目录,然后打印脚本所在的目录 . 例如,当使用
/home/mez/
中的脚本从/
调用它时,它会输出请记住,在从命令输出中分配变量时,将命令包装在
$(
和)
中 - 否则您将无法获得所需的输出 .如果你正在使用bash ....
正如马科所说:
除非您从脚本所在的同一目录执行脚本,否则这将起作用,在这种情况下,您将获得值“ . ”
要解决该问题,请使用:
您现在可以在整个脚本中使用变量current_dir来引用脚本目录 . 但是,这可能仍然存在符号链接问题 .
这个问题的最佳答案在这里得到了回答:
Getting the source directory of a Bash script from within
并且是:
One-liner将为您提供脚本的完整目录名称,无论它在何处被调用 .
要了解它是如何工作的,您可以执行以下脚本:
让它成为POSIX oneliner:
测试了许多与Bourne兼容的shell,包括BSD .
据我所知,我是作者,我将其置于公共领域 . 有关详细信息,请参阅:https://www.jasan.tk/posts/2017-05-11-posix_shell_dirname_replacement/
灵感来自blueyed’s answer
如此多的答案,都是合理的,每个答案都有不同的目标(可能应该针对每个目标进行说明) . 这是另一个解决方案,它满足所有系统的清晰和工作的主要目标,在所有bash上(没有关于bash版本或
readlink
或pwd
选项的假设),并合理地做你通常想要的事情,处理边缘情况,如路径中的空格等,忽略任何错误,并在出现任何问题时使用合理的默认值 .每个组件都存储在一个单独的变量中,您可以单独使用它:
INTRODUCTION
这个回答 corrects 这个帖子的非常破碎但令人震惊的最高投票回答(由TheMarko编写):
WHY DOES USING dirname "$0" ON IT'S OWN NOT WORK?
dirname $0 仅在用户以非常特定的方式启动脚本时才有效 . 我能够找到这种答案失败并崩溃脚本的几种情况 .
首先,让我们理解这个答案的工作原理 . 他正在通过这样做获取脚本目录
$0 表示调用脚本的命令的第一部分(它基本上是没有参数的输入命令:
$ 0 = “/一些/路径/./脚本”
dirname基本上找到字符串中的最后一个/并在那里截断它 . 所以,如果你这样做:
你会得到:/ usr / bin
这个例子效果很好,因为/ usr / bin / sha256sum是一个格式正确的路径但是
不会很好,会给你:
假设您与脚本位于同一个目录中,并使用此命令启动它
这种情况下的$ 0将是./script和dirname $ 0将给出:
使用:
如果没有输入完整路径,也会给出BASEDIR =“ . ”
使用相对目录:
给出一个0美元的名字:
如果你在/ some目录中并且以这种方式调用脚本(注意在开头没有/,再次是相对路径):
你将得到dirname $ 0的这个值:
和./path/./script(相对路径的另一种形式)给出:
basedir $0 将起作用的唯一两种情况是,如果用户使用sh或touch来启动脚本,因为两者都将导致$ 0:
哪个会给你一个您可以使用dirname的路径 .
THE SOLUTION
您已经考虑并检测上述每种情况,并在出现时对其应用修复:
这个单行代码告诉shell脚本在哪里,无论你运行它还是源代码都没关系 . 此外,它解决了所涉及的任何符号链接,如果是这样的话:
顺便说一句,我想你正在使用/ bin / bash .
这应该够了吧:
它可能看起来很难看,取决于它是如何被调用的和cwd但是应该让你到达你需要去的地方(或者你可以调整字符串,如果你关心它看起来如何) .