显示命令而不执行它们

pfn*_*sel 29 bash

我经常交互式循环例如我的文件,并希望对所有文件执行特定操作,假设我想重命名所有文件:

for file in $(ls); do mv "$file" "${file}_new"; done
Run Code Online (Sandbox Code Playgroud)

这很好用.但在调用此命令之前,我想看看它实际上做了什么,所以我会在前面添加一个回声

for file in $(ls); do echo mv "$file" "${file}_new"; done
Run Code Online (Sandbox Code Playgroud)

然后它会显示它将调用的所有命令.如果我对他们感到满意,我会删除echo并执行它.

但是,当命令更微妙时可能包括管道或多个命令时,这不再起作用.当然我可以使用,'所以特殊字符不会被解释,但后来我没有参数扩展.我也可以逃避特殊角色,但这会非常繁琐.

我的问题是,最好的方法是什么?我已经阅读了man bash关于该选项的选项-n,该选项执行"读取命令但不执行它们.这可用于检查shell脚本是否存在语法错误.交互式shell会忽略这一点." 这正是我需要的,但我需要它用于交互式shell.注意选项-x或者-v没有帮助,因为它不仅会显示命令,还会调用它,然后它可能已经太晚了.

dev*_*ull 27

这个线程会告诉你为什么显示命令而不是执行那些(也就是干运行)的选项永远不会实现bash.

请参阅Eric Blake的回复:

> 我的问题是为什么不能提供这样的选择或提供,

一点想法会说明为什么永远不会实现这一点.这样的选项会输出以下内容:

if complex_command; then
  foo=command1
else
  foo=command2
fi
$foo args
Run Code Online (Sandbox Code Playgroud)

在线上$foo args,没有办法知道$foo扩展到什么,除非你以前执行过(不仅仅是扫描) complex_command.因此,没有办法在不运行的情况下干掉最终结果,但是运行事情与干运行的目标背道而驰.

也就是说,您可能对该bashdb项目感兴趣,该项目使用bash钩子提供调试器接口,您可以单步执行bash脚本; 它与告诉你脚本会做什么不一样,但它至少可以让你控制脚本实际运行的程度.


Aar*_*lla 24

devnull解释的那样,"干运行"没有选项,但有一个简单的解决方法:

debug=
#debug=echo

$debug mv "$file" "${file}_new"
Run Code Online (Sandbox Code Playgroud)

如果从第二个分配中删除注释(不更改其他任何内容),则为危险mv命令启用"干运行" .

更复杂的方法是检查某些条件(如命令行选项):

debug=
if [[ ...enable dry run?... ]]; then
    debug=echo
fi
Run Code Online (Sandbox Code Playgroud)

注意:只有在-u启用了选项("将未设置的变量视为替换时的错误.")时,才需要空赋值.

重要提示:当命令使用重定向时,这将无法正常工作(因为shell在命令启动之前始终会执行这些操作).

  • @GeorgeVasiliou `debug` 只是一个局部变量,我要么不分配任何内容,要么只分配一个仅打印其参数的命令(`echo`)。要恢复效果,只需再次指定任何内容:“debug=”。 (2认同)

pfn*_*sel 9

有一个名为maybe 的github包,这是一个例子:

$ maybe rm file
> maybe has prevented rm file from performing 1 file system operations:
>
> delete /home/user/file
>
> Do you want to rerun rm file and permit these operations? [y/N]
Run Code Online (Sandbox Code Playgroud)


Rom*_*n M 5

实际上你可以在脚本中做到这一点

添加:

set -x # Print commands and their arguments as they are executed.
set -n # Read commands but do not execute them
Run Code Online (Sandbox Code Playgroud)

在脚本的开头

另外一个好的做法是添加set -e错误退出

(更多参考man集

  • 检查过。当一起使用两个开关时,我根本没有输出,也没有执行 (3认同)