我想翻译这个bash脚本介绍一个zsh脚本。因此我对此没有经验,希望我能在这里得到帮助:
bash脚本:
SCRIPT_PATH="${BASH_SOURCE[0]}";
if([ -h "${SCRIPT_PATH}" ]) then
while([ -h "${SCRIPT_PATH}" ]) do SCRIPT_PATH=`readlink "${SCRIPT_PATH}"`; done
fi
pushd . > /dev/null
cd `dirname ${SCRIPT_PATH}` > /dev/null
SCRIPT_PATH=`pwd`;
popd > /dev/null
我已经知道的是我可以使用
SCRIPT_PATH="$0";
获取脚本所在的路径。但后来我的“readlink”声明出错了。
感谢您的帮助
答案 0 :(得分:6)
除BASH_SOURCE
外,我发现您无需进行任何更改。但脚本的目的是什么?如果你想获取你的脚本所在的目录${0:A:h}
(:A
将解析所有符号链接,:h
将截断最后一个路径组件,留下你的目录名称):
SCRIPT_PATH="${0:A:h}"
就是这样。请注意,原始脚本有一些奇怪的事情发生:
if(…)
和while(…)
在子shell中启动…
。这里不需要子shell,只使用if …
和while …
进行这些检查会更快。 pushd .
。在使用pushd
时,您通常会将cd
来电替换为:
pushd "$(dirname $SCRIPT_PATH)" >/dev/null
SCRIPT_PATH="$(pwd)"
popd >/dev/null
cd `…`
输出带空格的内容,则…
将失败。目录可以包含空格。在上面的示例中,我使用了"$(…)"
,"`…`"
也可以使用。;
。readlink -f
将解析所有符号链接,因此您可以考虑将原始脚本缩减为SCRIPT_PATH="$(dirname $(readlink -f "${BASH_SOURCE[0]}"))"
(行为可能会因脚本似乎仅在最后一个组件中解析符号链接而改变):这是等效的bash到${0:A:h}
。if [ -h "$SCRIPT_PATH" ]
是多余的,因为除非脚本路径是符号链接,否则不会执行具有相同条件的while
正文。readlink $SCRIPT_PATH
将返回相对于包含$SCRIPT_PATH
的目录的符号链接。因此,原始脚本不可能用于解析最后一个组件中的符号链接。;
和if(…)
之间没有then
。我很惊讶bash接受这个。以上所有陈述均适用于bash和zsh。
如果只解析最后一个组件中的符号链接,那么你应该这样写:
SCRIPT_PATH="$0:a"
function ResolveLastComponent()
{
pushd "$1:h" >/dev/null
local R="$(readlink "$1")"
R="$R:a"
popd >/dev/null
echo $R
}
while test -h "$SCRIPT_PATH" ; do
SCRIPT_PATH="$(ResolveLastComponent "$SCRIPT_PATH")"
done
为了说明第7条陈述,有以下例子:
$R/bash
($R
是任何目录,例如/tmp
)。$R/bash/script_path.bash
下。在其末尾添加行echo "$SCRIPT_PATH"
,并在开始时添加行#!/bin/bash
进行测试。chmod +x $R/bash/script_path.bash
。cd $R/bash && ln -s script_path.bash link
。cd $R
$R/bash/1
。现在,您将看到您的脚本输出$R
,同时输出$R/bash
,就像您启动$R/bash/script_path.bash
时一样。