我想运行以下命令:
tar --sort=name --owner=root:0 --group=root:0 --mtime='UTC 2020-01-01' -cvf api.tar api
但 macOS 需要以下后备:
gtar --sort=name --owner=root:0 --group=root:0 --mtime='UTC 2020-01-01' -cvf api.tar api
(注意:参数是相同的。)
我可以gtar
先打电话,然后tar
作为后备,作为一句台词,只写一次参数吗?
答案1
我可以先调用 gtar,然后调用 tar 作为后备,作为一句台词,只写一次参数吗?
按要求回答这个问题:这可以通过将参数存储在数组中的简单实现来完成。 (Bash/ksh/zsh。参见我们如何运行存储在变量中的命令?了解问题和 POSIX 兼容的解决方法。)
args=(--sort=name --owner=root:0 --group=root:0 --mtime='UTC 2020-01-01' -cvf api.tar api)
if ! tar "${args[@]}"; then
echo "using 'tar' failed, retrying with 'gtar'" >&1
gtar "${args[@]}"
fi
或者作为一句台词,如果你坚持的话:
tar "${args[@]}" || gtar "${args[@]}"
虽然这并不能说明为什么它失败了,并且会尝试使用其他 tar 重试,即使问题类似于不可访问的目录。
另一种选择是仅在第一个命令出现“未找到命令”错误时重新运行该命令。$?
在这种情况下,shell 通常设置为 127。当然,这需要gtar
首先翻转,因为tar
可能以某种形式存在。
gtar "${args[@]}"
ret=$?
if [ "$ret" = 127 ]; then
tar "${args[@]}"
ret=$?
fi
该测试[ "$? = 127 ]
会丢弃 的值$?
,因此需要额外的变量来保存实际的退出状态。
在两个 tar 的具体情况下,拘萨罗南达的回答事先检查一下也是一个很好的解决办法。
答案2
tar
如果您通过在 macOS 上使用 Homebrew 安装包来安装 GNU gnu-tar
,您会在终端中看到以下消息:
GNU "tar" has been installed as "gtar".
If you need to use it as "tar", you can add a "gnubin" directory
to your PATH from your bashrc like:
PATH="/usr/local/opt/gnu-tar/libexec/gnubin:$PATH"
这意味着如果您首先按照上面的安装消息中所示tar
进行设置,则问题开头的命令将按预期工作。PATH
gnu-tar
PATH="/usr/local/opt/gnu-tar/libexec/gnubin:$PATH"
tar --sort=name --owner=root:0 --group=root:0 --mtime='UTC 2020-01-01' -cvf api.tar api
有条件更新PATH
:
if [ "$(uname)" = Darwin ]; then
PATH="/usr/local/opt/gnu-tar/libexec/gnubin:$PATH"
fi
tar --sort=name --owner=root:0 --group=root:0 --mtime='UTC 2020-01-01' -cvf api.tar api
您还可以使用以下方法进行测试command -v
:
if command -v gtar >/dev/null 2>&1; then
tar=gtar
elif command -v tar >/dev/null 2>&1 && tar --version | grep -q -F GNU 2>/dev/null; then
tar=tar
else
echo 'No GNU tar available' >&2
exit 1
fi
"$tar" --sort=name --owner=root:0 --group=root:0 --mtime='UTC 2020-01-01' -cvf api.tar api
这测试是否gtar
作为命令存在。如果是,则将该变量tar
设置为 string gtar
。如果不存在,我们测试tar
,如果tar
存在,我们测试是否tar --version
返回包含子字符串的内容GNU
并将tar
字符串分配给变量tar
。但如果测试失败,我们会通过诊断消息来退出。
稍后,如果我们没有因错误消息而退出,我们将使用"$tar"
as 命令。
uname
显然,您还可以选择对 的输出进行测试,
if [ "$(uname)" = Darwin ]; then
# Assumes GNU tar is gtar on macOS and that it's available
tar=gtar
else
# Assumes GNU tar is tar on this system, and that it's available
tar=tar
fi
"$tar" --sort=name --owner=root:0 --group=root:0 --mtime='UTC 2020-01-01' -cvf api.tar api