bash 在 shell 中的一行中运行多个命令

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/5130847/
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-09 20:14:00  来源:igfitidea点击:

Running multiple commands in one line in shell

bashshell

提问by John Redyns

Say I have a file /templates/appleand I want to

说我有一个文件/templates/apple,我想

  1. put it in two different places and then
  2. remove the original.
  1. 把它放在两个不同的地方,然后
  2. 取出原件。

So, /templates/applewill be copied to /templates/usedAND /templates/inuseand then after that I'd like to remove the original.

所以,/templates/apple将被复制到/templates/usedAND /templates/inuse,然后我想删除原来的。

Is cpthe best way to do this, followed by rm? Or is there a better way?

cp最好的方法,其次是rm?或者,还有更好的方法?

I want to do it all in one line so I'm thinking it would look something like:

我想在一行中完成所有操作,所以我认为它看起来像:

cp /templates/apple /templates/used | cp /templates/apple /templates/inuse | rm /templates/apple

Is this the correct syntax?

这是正确的语法吗?

回答by Maxim Egorushkin

You are using |(pipe) to direct the output of a command into another command. What you are looking for is &&operator to execute the next command only if the previous one succeeded:

您正在使用|(pipe) 将命令的输出定向到另一个命令。您正在寻找的是&&操作员仅在前一个命令成功时才执行下一个命令:

cp /templates/apple /templates/used && cp /templates/apple /templates/inuse && rm /templates/apple

Or

或者

cp /templates/apple /templates/used && mv /templates/apple /templates/inuse


To summarize (non-exhaustively) bash's command operators/separators:

总结(非详尽地)bash 的命令操作符/分隔符:

  • |pipes (pipelines) the standard output (stdout) of one command into the standard input of another one. Note that stderrstill goes into its default destination, whatever that happen to be.
  • |&pipes both stdoutand stderrof one command into the standard input of another one. Very useful, available in bash version 4 and above.
  • &&executes the right-hand command of &&only if the previous one succeeded.
  • ||executes the right-hand command of ||only it the previous one failed.
  • ;executes the right-hand command of ;always regardless whether the previous command succeeded or failed. Unless set -ewas previously invoked, which causes bashto fail on an error.
  • |管道 (pipelines) 将stdout一个命令的标准输出 ( ) 连接到另一个命令的标准输入。请注意stderr,无论发生什么情况,它仍然会进入其默认目的地。
  • |&将一个命令的stdout和管道传输stderr到另一个命令的标准输入中。非常有用,可在 bash 版本 4 及更高版本中使用。
  • &&&&仅当前一个成功时才执行右侧的命令。
  • ||仅执行||前一个失败的右侧命令。
  • ;;无论前一个命令是成功还是失败,都执行always的右侧命令。除非set -e之前被调用,这会导致bash错误失败。

回答by Marc B

Why not cpto location 1, then mvto location 2. This takes care of "removing" the original.

为什么不到cp位置 1,然后mv到位置 2。这负责“删除”原始文件。

And no, it's not the correct syntax. |is used to "pipe" output from one program and turn it into input for the next program. What you want is ;, which seperates multiple commands.

不,这不是正确的语法。|用于从一个程序“管道”输出并将其转换为下一个程序的输入。你想要的是;,它分隔多个命令。

cp file1 file2 ; cp file1 file3 ; rm file1

If you require that the individual commands MUST succeed before the next can be started, then you'd use &&instead:

如果您要求单个命令必须成功才能启动下一个命令,那么您可以&&改用:

cp file1 file2 && cp file1 file3 && rm file1

That way, if either of the cpcommands fails, the rmwill not run.

这样,如果其中一个cp命令失败,rm则不会运行。

回答by glenn Hymanman

Note that cp A B; rm Ais exactly mv A B. It'll be faster too, as you don't have to actually copy the bytes (assuming the destination is on the same filesystem), just rename the file. So you want cp A B; mv A C

请注意,cp A B; rm A正是mv A B. 它也会更快,因为您不必实际复制字节(假设目标位于同一文件系统上),只需重命名文件即可。所以你要cp A B; mv A C

回答by Eyal Levin

Another option is typing Ctrl+VCtrl+Jat the end of each command.

另一种选择是Ctrl+VCtrl+J在每个命令的末尾键入。

Example (replace #with Ctrl+VCtrl+J):

示例(替换#Ctrl+VCtrl+J):

$ echo 1#
echo 2#
echo 3

Output:

输出:

1
2
3

This will execute the commands regardless if previous ones failed.

无论以前的命令是否失败,这都会执行命令。

Same as: echo 1; echo 2; echo 3

与...一样: echo 1; echo 2; echo 3

If you want to stop execution on failed commands, add &&at the end of each line except the last one.

如果要停止执行失败的命令,请&&在除最后一行之外的每一行末尾添加。

Example (replace #with Ctrl+VCtrl+J):

示例(替换#Ctrl+VCtrl+J):

$ echo 1 &&#
failed-command &&#
echo 2

Output:

输出:

1
failed-command: command not found


In zshyou can also use Alt+Enteror Esc+Enterinstead of Ctrl+VCtrl+J

zsh你也可以使用Alt+EnterEsc+Enter代替Ctrl+VCtrl+J

回答by Peter

Try this..

尝试这个..

cp /templates/apple /templates/used && cp /templates/apple /templates/inuse && rm /templates/apple

cp /templates/apple /templates/used && cp /templates/apple /templates/inuse && rm /templates/apple

回答by Renaud

Using pipes seems weird to me. Anyway you should use the logical andBash operator:

使用管道对我来说似乎很奇怪。无论如何,您应该使用逻辑andBash 运算符:

$ cp /templates/apple /templates/used && cp /templates/apple /templates/inuse && rm /templates/apples

If the cpcommands fail, the rmwill not be executed.

如果cp命令失败,rm则不会执行。

Or, you can make a more elaborated command line using a forloop and cmp.

或者,您可以使用for循环和cmp.