简体   繁体   English

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

[英]Running multiple commands in one line in shell

Say I have a file /templates/apple and I want to 说我有一个文件/templates/apple并且我想要

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

So, /templates/apple will be copied to /templates/used AND /templates/inuse and then after that I'd like to remove the original. 因此, /templates/apple将被复制到/templates/used/templates/inuse ,然后在此之后,我想删除原始文件。

Is cp the best way to do this, followed by rm ? cp是执行此操作的最佳方法,其次是rm吗? Or is there a better way? 或者,还有更好的方法?

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? 这是正确的语法吗?

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: 您正在寻找的是&&运算符,只有前一个命令成功执行才能执行下一个命令:

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. 将一个命令的标准输出( stdout )用管道stdout到另一个命令的标准输入中。 Note that stderr still goes into its default destination, whatever that happen to be. 请注意,无论发生什么情况, stderr仍会进入其默认目的地。
  • |& pipes both stdout and stderr of one command into the standard input of another one. |&将一个命令的stdoutstderrstderr到另一命令的标准输入中。 Very useful, available in bash version 4 and above. 非常有用,在bash版本4及更高版本中可用。
  • && 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 -e was previously invoked, which causes bash to fail on an error. 除非先前曾调用set -e ,否则这将导致bash因错误而失败。

Why not cp to location 1, then mv to 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 cp commands fails, the rm will not run. 这样,如果任何一个cp命令失败,则rm将不会运行。

Note that cp AB; rm A 注意cp AB; rm A cp AB; rm A is exactly mv AB . cp AB; rm A就是mv AB 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 AB; mv AC 所以你想要cp AB; mv AC cp AB; mv AC

Another option is typing Ctrl+V Ctrl+J at the end of each command. 另一个选项是在每个命令的末尾键入Ctrl + V Ctrl + J。

Example (replace # with Ctrl+V Ctrl+J ): 示例(用Ctrl + V Ctrl + 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 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+V Ctrl+J ): 示例(用Ctrl + V Ctrl + J替换# ):

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

Output: 输出:

1
failed-command: command not found

In zsh you can also use Alt+Enter or Esc+Enter instead of Ctrl+V Ctrl+J zsh您也可以使用Alt + EnterEsc + Enter代替Ctrl + V Ctrl + J

尝试这个..

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

Using pipes seems weird to me. 使用管道对我来说很奇怪。 Anyway you should use the logical and Bash operator: 无论如何,您应该使用逻辑and Bash运算符:

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

If the cp commands fail, the rm will not be executed. 如果cp命令失败,则不会执行rm

Or, you can make a more elaborated command line using a for loop and cmp . 或者,您可以使用for循环和cmp制作更详细的命令行。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM