如何在 bash shell 脚本中回显命令,但不执行它们?

如何在 bash shell 脚本中回显命令,但不执行它们?

有没有办法运行 shell 脚本并回显命令没有实际执行它们?

假设我有一个脚本删除一个名称存储在变量中的文件:

#!/bin/bash
set -v
FN="filename"
rm -f ${FN}

添加set -v后将在执行前回显以下命令:

$ ./scr.sh
FN="filename"
rm -f ${FN}

现在,我想查看此脚本的流程,但实际上不删除文件。换句话说,我想防止对外部环境和文件系统产生任何影响。这可能吗?

我可以用一个命令包装所有命令echo,但是对于长脚本来说这很累。

答案1

如果不实际执行,就无法逐步执行脚本以查看其执行方式。在您的示例中,没有if语句或循环。但在实际脚本中,通常有很多条件语句。哪个分支将被采用通常取决于 shell 运行上一个命令时发生的情况。如果它不运行该命令,shell 就无法知道它会生成什么输出或返回代码是什么,下一个条件分支或赋值语句可能依赖于此。

如果您想在运行脚本之前仔细检查并了解其功能,那么这不失为一个好主意。但实际上,最好的方法是使用或lessvi类似的东西浏览文件。

添加

如果您正在开发一个脚本,并且想要第一次就逐步完成它,测试逻辑但如果有错误实际上不会造成任何损害,我经常使用的解决方案是仅修改可能造成损害的语句,方法是将其粘贴到echo前面。

这通常在典型的实际脚本中起作用,因为(a)生成您将迭代的项目列表或您将设置变量的值通常可以在不更改文件系统的情况下生成,并且(b)通常足以假设如果您确实运行了该命令,它就会成功。

答案2

我认为您将不得不回显 - 但是如果您将命令放在变量中,则可以将其打开和关闭。此外,命令可以是函数,并且可以根据需要复杂化。

#!/bin/bash
echo 'Debug'
  D=echo
  :>| testy
  ls -l testy
  $D rm -f testy
  ls -l testy
echo $'\n\nLive'
  D=
  :>| testy
  ls -l testy
  $D rm -f testy
  ls -l testy

==================================================

!$ > ./conditional.sh
Debug
-rw-rw-r-- 1 nobody nobody 0 2013-01-18 15:28 testy
rm -f testy
-rw-rw-r-- 1 nobody nobody 0 2013-01-18 15:28 testy

Live
-rw-rw-r-- 1 nobody nobody 0 2013-01-18 15:28 testy
ls: cannot access testy: No such file or directory

答案3

您可以使用 bash 的 -x 选项来跟踪流程,但这仍会执行命令。

您能做的最好的事情就是只添加 echo 或注释掉具有外部效果的命令(如 rm)。至少您不必更改每一行。

答案4

这是我喜欢使用的一个小构造:

#!/bin/sh

verbose=false
really=true

# parse arguments
while [ $# -ge 1 ]
do
  case "$1" in
    -v) verbose=true ;;
    -n) really=false; verbose=true ;;
  esac
  shift
done

doCmd() {
  if $verbose; then echo "$@"; fi
  if $really; then "$@"; fi
}

doCmd make foo
doCmd rm -rf /tmp/installdir
doCmd mkdir /tmp/installdir
doCmd whatever
doCmd blah blah

相关内容