`>`和`>>`如何工作?


9

我尝试了rev一个文件,然后将其通过管道传输到它,cat > same_file但是它变成了空白文件。

当我尝试rev file.txt | cat > file2.txt && mv file.txt file2.txt;它的时候。

甚至rev file.txt | cat >> file.txt;工作。

但是当我尝试时,rev file.txt | cat > file.txt它失败了。


您也可以留下cat了这样的:rev file.txt > file2.txt && mv file2.txt file.txt。这是的多余用法cat。通过省略它,您可以多余地产生额外的过程。
matega 2015年

Answers:


19

在这种情况下,两种重定向方式(>和>>)之间需要掌握的基本知识是:

>

重定向并覆盖指向的信息。通过管道“ |”接收任何信息时,会发生这种情况

>>

重定向并连接到所指向的信息。通过管道“ |”接收任何信息时,会发生这种情况

在这两种情况下,如果文件都不存在,则会创建该文件。如果在同一文件上再次运行该信息,则仅在“ >>”上将其串联。使用“>”,您将简单地覆盖您在第一次运行中所做的一切。

但是,当使用与输出文件相同的输入文件时,这就是问题。在这种特定情况下,如果使用“>”,则将删除“输入”部分需要解析的信息,因为输出文件将“覆盖它”。所以在:

rev file.txt | cat > file.txt

“慢动作说明”中实际发生的是:

  1. rev准备反转内容file.txt并将其发送到管道
  2. rev将信息发送到管道时,管道将其直接流传输到cat
  3. cat接收信息时,它将自动将其应用于file.txt设置的信息。
  4. 此处的关键字是“ while”,因为所有事情都是同时发生的。请查看以下Emil的精彩评论,以加深对这一部分的了解。
  5. cat不会等待rev管道整个文件。它只会从信息第一部分开始的那一刻开始,这意味着,根据您使用的符号,它将打开与的连接file.txt
  6. 在这种情况下,由于使用了>而不是>>,因此Shell将截断输出文件,这意味着它将在等待新信息到达时打开并清除信息file.txt。使用>>,它将打开与的连接,file.txt并在检测到的最后一行上等待新信息。
  7. 由于已file.txt使用>清除了该信息,因此rev将尝试执行该操作,但一无所获,因为cat删除了所有内容以准备新信息。

那么为什么其他人在阅读了上面的内容后仍然可以工作。因为这:

rev file.txt | cat > file2.txt && mv file.txt file2.txt

在这里,您正在使用cat来将信息发送到另一个文件。在这种情况下,处理后的输入文件file.txt与输出文件不同file2.txt。之后,你是从字面上覆盖全file2.txtfile.txt,因此所有提出的过程中cat被删除。基本上,可以简化整行,cp file.txt file2.txt因为它在做同样的事情,因为file2.txt最后放宽了rev,并被mv命令覆盖。

rev file.txt | cat >> file.txt

在这种情况下,您要将信息串联到同一文件中。因此,它仅打开与该文件的连接,而不会擦除如单个>所示的信息。最终结果应该是原始信息加上反向信息。


5
该文件不会被cat截断。在启动管道中的任何命令之前,shell都会将其截断。
EmilJeřábek,2015年

正确,正在寻找更容易解释的单词。由于很难解释OP是否不知道它是什么外壳以及所有其他内容。试图使其尽可能“友好”。
路易斯·阿尔瓦拉多

1
好吧,它由外壳程序完成并不重要,但是您提供的时间是错误的。截断不会在步骤6中发生,但是在步骤0中rev file.txt | cat --bogus-option > file.txt也会截断该文件,即使cat不会尝试打开它也是如此。
EmilJeřábek2015年

@EmilJeřábek你是正确的。如果我们仅使用命令逐步进行操作,仍然不知道它的行为的用户将会更容易。同样,您的示例仍将信息发送到同一文件,因此bash会读取整行,查看输出并仍然打开并截断它。错误只是stderr输出到stdout。
路易斯·阿尔瓦拉多

4
另请参见moreutils,这是一个很棒的工具集合(可从软件包存储库中获得moreutils),其中包括sponge专门为覆盖输入文件的用例而设计的工具。例如,rev file.txt >file2.txt && mv file2.txt file.txt变通方法将变为rev file.txt | sponge file.txt,即使已经存在名为的方法也可以正常工作file2.txt
Daniel Wagner 2015年

9

当Shell看到重定向时,它将先打开相关文件,然后再执行任何涉及的命令。因此,当您这样做时:

foo file.txt | bar > file.txt

重定向到file.txt导致它 foo运行之前被截断并且可以读取file.txt。附带说明,这就是为什么您不能这样做:

sed 'blah' file.txt > file.txt

以及为什么sed具有就地编辑选项。

最后,执行以下操作:

.. | cat > file.txt

cat的无用用法,尤其是如果您尝试file.txt从前阅读时。

如果要就地还原文件,则没有快捷方式。您可能可以在现场编辑中使用sedawk技巧。


3

>是重定向器(运算符),将输出发送到其他东西
(下一个命令的输入,打印机..)

在您的情况下,输出将进入一个文件file.txt,如果该文件已经存在,则将其覆盖,否则将被创建。

>>是一个追加运算符,如果file.txt已经存在,则将输出追加到文件末尾。如果文件不存在,则会创建该文件,并将输出写入新文件,与>(重定向器)相同。


OP似乎已经了解了这一点。混淆似乎仅源于>and >>运算符两侧的同一文件。
bzlm

0

您可以在Ex模式下使用Vim:

ex -sc '%!rev' -cx file.txt
  1. % 选择所有行

  2. ! 运行命令

  3. x 保存并关闭

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.