我想要一个运行命令并将其附加到文件的通用脚本。
我的尝试如下(存储在名为 的可执行文件中./action
)。
#!/bin/bash
#runs command and logs result to "./actions"
if "$@"; then
echo "#"$(date)"(success)" >> ./actions
else
read -p "Exit code is fail. Still record to ./actions (y)? " -n 1 -r
echo
if [[ ! $REPLY =~ ^[Yy]$ ]]
then
exit 1
fi
echo "#"$(date)"(failed)" >> ./actions
fi
echo "$@" >> ./actions
我遇到的问题是:
./action touch "new file"
运行正确,但 bash 仅保存
touch new file
显然touch new file
与 不同touch "new file"
。
如何修复此脚本以正确记录带引号参数的命令?
答案1
有趣的问题。我认为你想要做的事情并不完全可能,但你可以使用Bash实现%q
中可用的格式说明符来非常接近:printf
%q 导致 printf 以可重复用作 shell 输入的格式输出相应的参数。
脚本中的最后几行可能如下所示:
printf "%q\n" "$@" | tr '\n' ' ' >> actions
printf "\n" >> actions
这不会完全按照您键入的方式记录命令,而是以适合在 shell 中使用的形式记录命令,如果您键入这些记录的命令,您将获得最初预期的结果。例如,执行此操作后:
./action touch "new file"
你得到:
#Wed Sep 4 14:10:57 CEST 2019(success)
touch new\ file
或者执行此操作后:
./action echo 'one
two
three
'
你得到:
#Wed Sep 4 14:11:44 CEST 2019(success)
echo $'one\ntwo\nthree\n'
作为旁注,shellcheck
报告脚本中的 2 个错误:
$ ~/.cabal/bin/shellcheck action
In action line 5:
echo "#"$(date)"(success)" >> ./actions
^-- SC2027: The surrounding quotes actually unquote this. Remove or escape them.
^-- SC2046: Quote this to prevent word splitting.
In action line 13:
echo "#"$(date)"(failed)" >> ./actions
^-- SC2027: The surrounding quotes actually unquote this. Remove or escape them.
^-- SC2046: Quote this to prevent word splitting.