当您想运行多个命令时,可以使用;
,&&
和|
像这样:killall Finder; killall SystemUIServer
,cd ~/Desktop/ && rm Caches
或者:man grep | man cat
例如。
|
但是,;
和之间有区别吗&&
?如果是这样,有什么区别?
答案1
;
:以a分隔的命令;
按顺序执行。 shell 依次等待每个命令终止。&&
:当且仅当 command before返回退出状态为零&&
时,才执行command after。&&
您可以将其视为AND
运算符。|
: 管道。在表达式中,command1 | command2
command1 的标准输出通过管道连接到command2 的标准输入。
还有更多类似的控制运算符,值得一提:
||
:||
当且仅当 command before||
返回非零退出状态时,command after 才会执行。您可以将其视为OR
运算符。请注意,那|
和||
是完全不同的动物。&
:shell&
在后台执行由 终止的命令,不等待命令完成并立即返回退出代码 0。再次&
与 无关&&
。|&
2>&1 |
:即command1的标准输出和标准错误都通过管道连接到command2的标准输入的简写。
此外,如果您使用zsh
then 您还可以使用&|
或启动命令&!
。在这种情况下,作业立即被拒绝,启动后它在作业表中没有位置。
答案2
考虑两个命令A
和B
。当你写
A | B
A
和B
并行执行,并且 的标准输出A
作为 的标准输入发送B
。
当你写的时候
A; B
A
被执行,然后B
被执行(除非set -e
已被使用并A
以非零退出状态终止,在这种情况下,shell 在 后立即终止A
)。
当你写的时候
A && B
A
被执行,然后仅在成功终止(零退出状态)B
时执行。A
这种形式比前一种形式更安全,例如
cd some_dir && rm file*
确保&&
删除正确的文件,即仅在cd
成功时才删除文件。
答案3
其他答案已经解释了|
,&&
和;
,所以我将添加一些您没有明确要求的额外内容:||
。
A || B
A
被执行,然后仅在失败B
时执行。A
这对于对错误情况做出反应很有用:
martin@martin ~ % rm doesnotexist 2>/dev/null || echo "failed to delete file"
failed to delete file
(2>/dev/null
有必要隐藏rm
其自身的错误消息。)
答案4
鉴于您的实际示例,似乎没有人解释您为什么要使用每一个。我会尝试一下:
killall Finder; killall SystemUIServer
像这样的命令killall
可能需要一些时间才能执行。通过使用分号,您可以同时发出两个命令,然后在等待时执行其他操作。这样您就不必等待两次(每个命令一次)。
cd ~/Desktop/ && rm Caches
您想要删除该目录~/Desktop/Caches
并最终进入该目录~/Desktop
。您不想做的是从当前目录中删除目录 Caches(在更改它之前)。因此&&
,在执行删除命令之前, 您需要检查目录更改是否成功。
man grep | man cat
这对我来说毫无意义。该man
命令不处理输入,因此通过管道传递给它不会执行任何操作。也许你的意思是
man grep || man cat
它会尝试查找 的手册页grep
,如果找不到,则会显示 的手册页cat
。或者可能你的意思是
man grep | cat
这将用于cat
显示手册页而不是寻呼机(通常less
)。将|
输出重定向man
到命令cat
(将所有内容转储到屏幕)。这在 GUI 中很有用,您可以使用滚动条在文件中来回移动,而不是在 less 中使用键盘命令。
注意:如果您想知道;
&&
|
||
在更一般的情况下该怎么做,那么我建议查看 jimmij 的答案。我只是想解释问题示例中发生的情况。