bash 显示命令而不执行它们

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/19115156/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-10 00:16:26  来源:igfitidea点击:

Show commands without executing them

bash

提问by pfnuesel

I often interactively loop over e.g. my files and want to perform a specific operation on all of them, let's say I'd like to rename all files:

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

for file in $(ls); do mv "$file" "${file}_new"; done

This works fine. But before invoking this command, I'd like to see what it actually does, so I would add an echo in front

这工作正常。但是在调用这个命令之前,我想看看它实际上做了什么,所以我会在前面添加一个 echo

for file in $(ls); do echo mv "$file" "${file}_new"; done

it then shows me all the commands it would invoke. If I'm happy with them, I remove the echoand execute it.

然后它向我展示了它会调用的所有命令。如果我对它们感到满意,我会删除echo并执行它。

However, when the commands are a bit more subtle maybe including pipes or more than one command, this doesn't work anymore. Of course I could use 'so the special characters don't get interpreted, but then I don't have parameter expansion. I could also escape the special characters, but this would get very tedious.

但是,当命令更加微妙时,可能包括管道或多个命令,这将不再起作用。当然我可以使用'这样特殊字符不会被解释,但是我没有参数扩展。我也可以转义特殊字符,但这会变得非常乏味。

My question is, what's the best way to do this? I've read in man bashabout the option -n, which does "Read commands but do not execute them. This may be used to check a shell script for syntax errors. This is ignored by interactive shells." This is exactly what I need, but I need it for an interactive shell. Note that the options -xor -vdo not help, as it will not only show the command, but also invoke it and then it might be too late already.

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

采纳答案by devnull

Thisthread would tell you why the option to show commands instead of executing those (a.k.a dry run) would never be implemented for bash.

线程将告诉你为什么选项show命令而不是执行者(又名干转)永远不会为实施bash

Refer to the response from Eric Blake:

请参阅Eric Blake的回复:

>My question is why can't such an option or be provided,

A little thought would show why this will never be implemented. What would such an option output for the following:

if complex_command; then
  foo=command1
else
  foo=command2
fi
$foo args

On the line for $foo args, there is no way to know what $fooexpands to unless you have previously executed (not just scanned) the complex_command. Therefore, there is no way to dry run what the final results will be without running things, but running things is counter to the goal of a dry run.

That said, you might be interested in the bashdbproject, which uses bash hooks to provide a debugger interface where you can single-step through a bash script; it's not the same as telling you what the script would do, but it at least lets you control how much or little of the script is actually run.

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

稍加思考就会说明为什么这永远不会实施。对于以下情况,这样的选项会输出什么:

if complex_command; then
  foo=command1
else
  foo=command2
fi
$foo args

在 for 行上$foo args$foo除非您之前已执行(不只是扫描) complex_command. 因此,不运行东西就无法试运行最终的结果,但运行东西与试运行的目标背道而驰。

也就是说,您可能对该bashdb项目感兴趣,该项目使用 bash 钩子提供调试器接口,您可以在其中单步执行 bash 脚本;这与告诉您脚本会做什么不同,但它至少可以让您控制实际运行的脚本的数量。

回答by Aaron Digulla

There is no option for "dry run" as explained by devnullbut there is a simple workaround:

正如devnull解释的,没有“试运行”选项,但有一个简单的解决方法:

debug=
#debug=echo

$debug mv "$file" "${file}_new"

If you remove the comment from the second assignment (without changing anything else), you enable "dry run" for the dangerous mvcommand.

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

A more elaborate approach would be to check some condition (like a command line option):

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

debug=
if [[ ...enable dry run?... ]]; then
    debug=echo
fi

Note: The empty assignment is only necessary when you have the option -u("Treat unset variables as an error when substituting.") enabled.

注意:只有当您-u启用了选项(“替换时将未设置的变量视为错误。”)时,才需要空分配。

Important:This won't work well, when your commands use redirections (because the shell will always do them before the command is even started).

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

回答by pfnuesel

There is a githubpackage called maybe, here's an example:

有一个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]

回答by Roman M

Actually you can do this in a script

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

add:

添加:

set -x 
set -n

in the beginning of the script

在脚本的开头