我正在编写bash脚本,在Ubuntu中使用“ sh”命令时会引发错误(似乎与破折号不兼容,我正在学习此主题)。因此,我想检测是否使用破折号而不是bash引发错误。
如何在脚本上下文中检测到它?可能吗?
您可以检查是否存在特定于shell的变量:
例如,bash定义$BASH_VERSION。由于在中运行时不会定义该变量dash,因此可以使用它来进行区分:
[ -n "$BASH_VERSION" ] && isBash=1
Run Code Online (Sandbox Code Playgroud)
事后思考:如果您想避免依赖变量(很可能设置不正确),则可以通过确定调用的可执行文件(如果它是符号链接)来尝试获取运行脚本的Shell可执行文件的最终名称。跟随其(最终)目标。
下面的shell函数可以getTrueShellExeName()做到这一点;例如,它将'dash'在Ubuntu上返回运行的脚本sh(无论是显式的还是通过shebang #!/bin/sh),因为它sh是符号链接到dash那里的。
请注意,该函数的目标是双重的:
注意事项:
sh,即使OSX 有效,它也不是符号链接bash。在那里,该函数将'sh'在使用运行的脚本中返回sh。readlink了POSIX并未强制要求的功能,但在大多数现代平台上都存在该功能-尽管语法和功能有所不同。因此,使用GNU readlink的-f选项,找到一个符号链接的最终目标是不是一种选择。readlink实用程序是HP-UX -请参阅/sf/answers/1687983951/一个递归的readlink实施,应该在工作的所有 POSIX平台。 )which实用程序(除外zsh,它是内置的),虽然不是POSIX强制要求的,但在大多数现代平台上都存在。函数使用示例:
[ "$(getTrueShellExeName)" = 'bash' ] && isBash=1
Run Code Online (Sandbox Code Playgroud)
外壳功能getTrueShellExeName():
getTrueShellExeName() {
local trueExe nextTarget 2>/dev/null # ignore error in shells without `local`
# Determine the shell executable filename.
trueExe=$(ps -o comm= $$) || return 1
# Strip a leading "-", as added e.g. by OSX for login shells.
[ "${trueExe#-}" = "$trueExe" ] || trueExe=${trueExe#-}
# Determine full executable path.
[ "${trueExe#/}" != "$trueExe" ] || trueExe=$([ -n "$ZSH_VERSION" ] && which -p "$trueExe" || which "$trueExe")
# If the executable is a symlink, resolve it to its *ultimate*
# target.
while nextTarget=$(readlink "$trueExe"); do trueExe=$nextTarget; done
# Output the executable name only.
printf '%s\n' "$(basename "$trueExe")"
}
Run Code Online (Sandbox Code Playgroud)
使用 $0(即被调用的 shell 的可执行文件的名称)。例如命令
echo $0
Run Code Online (Sandbox Code Playgroud)
给
/usr/bin/dash
Run Code Online (Sandbox Code Playgroud)
对于破折号和
/bin/bash
Run Code Online (Sandbox Code Playgroud)
对于 bash. 参数替换
${0##*/}
Run Code Online (Sandbox Code Playgroud)
只给出 'dash' 或 'bash'。这可以在测试中使用。