为什么要在 Bash 脚本的一行上组合命令?

为什么要在 Bash 脚本的一行上组合命令?

我是 Linux 和 Bash 脚本的新手。在工作中,我见过类似以下结构的 Bash 脚本:

mkdir build && cd build && touch blank.txt

或者:

mkdir build; cd build; touch blank.txt

甚至是异国情调的:

COMMAND="mkdir build && cd build && touch blank.txt"
eval ${COMMAND}

最后一个例子给出了一个可能的用例,其中单行可能有用,但通常以下内容更容易阅读并且(至少对我来说)允许您直观地调试脚本:

mkdir build
cd build
touch blank.txt

将所有内容塞到一行上是否有技术优势?

答案1

mkdir build && cd build && touch blank.txt

在 Bash(以及其他一些 shell 和大多数高级编程语言)中,&&逻辑,这意味着 - 如果前一个命令返回 true,则将执行下一个命令。还有逻辑或者 ||。例如,您可以在一个语句中组合这两个选项:

mkdir /tmp/abc/123 && echo 'the dir is created' || echo "the dir isn't created"

注意,构造cmd_1 && cmd_2 || comd_3不能替代语句if.. then.. else,因为无论前面哪个命令返回 false,都会cmd_3执行。因此,您必须小心使用它的情况。以下是一个例子:

$ true && false || echo success
success
$ false && true || echo success
success
$ false && false || echo success
success

根据经验,通常,当我cd在脚本中使用命令时,我会测试目录更改是否成功:cd somewhere/ || exit。更合适的测试是由 @dessert 提议: if ! cd dir; then exit 1; fi。但在所有情况下,作为保护脚本失败,最好使用选项,set -e因为它显示在@mrks 的回答


mkdir build; cd build; touch blank.txt

;是行分隔符,当在一行中写入几个分隔命令时使用它。


注意,当使用;&&||时,不一定要将命令写在一行中 - 这在@allo 的回答

在我看来,在一行或多行中写入命令之间没有任何特殊的技术优势/差异。


COMMAND="mkdir build && cd build && touch blank.txt"
eval ${COMMAND}

在这里,一个或多个命令(及其参数)被分组为一个变量的值,然后借助 将此变量(参数)转换为命令eval。因此,您只需在一个地方进行更改,即可更改某个脚本中将多次执行的命令。

假设您需要更改文件的创建方式blank.txt,例如,您可以按照以下方式更改相关行:

COMMAND="mkdir build && cd build && echo 'test' > blank.txt"

实际eval优势过度使用alias是当有重定向、管道、逻辑运算符- 所有控制流操作符均在使用中。

在大多数情况下,当不适用时,您可以使用functions而不是。同样,如果变量仅包含单个命令,即,我们不需要,因为 Bash 单词拆分将正确扩展。evalaliasCMD="cat"eval"$CMD" "$file1" "$file2"

答案2

到目前为止的答案解决了发生了什么/它是如何工作的,但我认为你问的是“为什么”

对我来说,这样做而不是在三行上输入它们的主要“原因”是,有时命令需要时间(有时是几分钟)并且您不想一直等待。

例如,我可能会构建&&部署&&启动我的应用程序,然后出去吃午饭。这个过程可能需要 15 分钟才能完成。但是因为我使用了&&,所以如果构建失败,它就不会部署——所以这是可行的。

预输入是一种替代方法,但它不太可靠,您可能无法看到您输入的内容(因此会犯错误)或者程序可能会吃掉预输入(谢谢,grails!)。然后您吃完午饭回来发现由于打字错误,您还有两个较长的任务要开始。

另一种选择是编写一个小脚本或别名。这主意不错,但灵活性不够,就像我一样:

stop && build && test && deploy && start 

或者我可以:

stop && start

或者任何其他组合,这些组合都会很快用一堆标志污染脚本。

即使您确实编写了脚本,您也可能将其与其他脚本集成在一起&&

答案3

在 Linux 上组合命令可能非常有用。

一个很好的例子可能通过 ssh 重新启动远程网络接口(如果您更改了网络配置或其他内容...)。

ifdown eth0 && ifup eth0

这可以防止您物理访问服务器以调出您最初通过 ssh 连接的界面。ifup eth0(如果ifdown eth0单独执行,则无法执行。)

答案4

另一个原因可能在于脚本的形成方式:技术用户通常会构建非常长的交互式命令行,反复扩展和测试它们,直到它们按预期工作,然后将结果粘贴到文本文件中并在上面添加标题#!/bin/bash。有时,脚本的多个部分是通过这种方法演变而来的。

for i in以、链开头的长单行构造grep | cut | sed | xargs、大量使用&&和构造通常表明此类起源。||$(cat something)

相关内容