我将其用作bash
我的主要 shell,但这是一个开放的问题,对于其他 shell 的回答也bash
非常受欢迎。
如果我以交互方式打字
#original line
#wget http://something.com && unzip something && mv -f something /home/poney/
#new line
wget http://something.com ; unzip something ; mv -f something /home/poney/
与包含这些行的脚本相比,它在执行堆、顺序、内存、解释、权限方面有什么区别吗:
#!/bin/bash
wget http://something.com
unzip something
mv -f something /home/poney/
附:
除了执行脚本显然比连续输入 3 个命令要短这一事实之外。
答案1
是的,有很大的不同。 &&
是短路,因此仅当前一个命令返回退出代码为 时,才会执行后续命令0
。
引用自手动的:
表达式1
&&
表达式2True if both expression1 and expression2 are true.
另一方面,一个脚本包含
expression1
expression2
即使第一个表达式失败也会执行第二个表达式。 (除非您通过说指定脚本在出错时退出set -e
。)
编辑:关于您的评论是否:
command1; command2
是相同的:
command1
command2
答案是通常。 Bash 在评估任何一个语句块之前都会解析整个语句块。 A ;不会导致评估前一个命令。如果前一个命令影响后一个命令的解析方式,那么您会注意到其中的差异。
考虑一个包含别名的文件,我们称之为alias
,并带有一个条目:
alias f="echo foo"
现在考虑一个包含以下内容的脚本:
shopt -s expand_aliases
source ./alias
f
另一个包含:
shopt -s expand_aliases; source ./alias; f
那么您可能会认为两者都会产生相同的输出。
答案是不。第一个会产生,foo
但第二个会报告:
... f: command not found
进一步澄清一下,这并不是expand_aliases
造成问题的原因。问题是由于这样的语句:
alias f="echo foo"; f
将会解析的一气呵成。 shell 并不真正知道f
是什么,这会导致解析器卡住。
答案2
是的,&&
是条件。仅当前一个命令返回0
(结束且没有错误)时,后面的命令才会启动。另一方面,您的脚本没有此控件,因此如果例如。 wget 以错误结束,它将继续并尝试解压缩并移动任何内容。
您的脚本的在线版本是:
wget http://something.com ; unzip something ; mv -f something /home/poney/
答案3
与上述的另一个区别是您的 shell 脚本在单独的 shell 中运行,因此对环境的任何更改都不会传播出去。例如,如果您在交互式 shell 中输入
test -f foo && file=foo || file=other
那么您的交互式 shell 将包含一个变量file
(您可以使用 读取$file
),其中包含foo
文件 foo 是否存在并且是常规文件,other
否则。现在,如果您将相同的内容放入 shell 脚本中并从交互式 shell 中调用它,则file
交互式 shell 中的变量将不会被设置(但当然在 shell 脚本中它将被设置,因此您可以在进一步的命令中使用它)其中)。