voi*_*hos 11 shell io-redirection
我.hgignore
今天试图从 Cygwin bash shell快速编辑一个文件,但我添加了一行错误。我不确定这是否是最好的方法,但我很快想到使用head -1 .hgignore
删除有问题的行(我以前在文件中只有一行)。果然,执行时它给出了第一行作为唯一的输出。
但是当我尝试重定向输出并使用 重写文件时head -1 .hgignore > .hgignore
,该文件为空。为什么会发生这种情况?如果我尝试附加,head -1 .hgignore >> .hgignore
,它会正确附加,但这显然不是想要的结果。为什么在这种情况下截断重定向不起作用?
Cal*_*leb 13
我认为布鲁斯用 shell 管道回答了这里发生的事情。
我最喜欢的小工具之一是sponge
来自moreutils的命令。它通过在打开目标输出文件并写入数据之前“吸收”所有可用输入来解决这个问题。它允许您完全按照您的预期编写管道:
$ head -1 .hgignore | sponge .hgignore
Run Code Online (Sandbox Code Playgroud)
穷人的解决方案是将输出通过管道传输到临时文件,然后在管道完成后(例如您运行的下一个命令)将临时文件移回原始文件位置。
$ head -1 .hgingore > .hgignore.tmp
$ mv .hgignore{.tmp,}
Run Code Online (Sandbox Code Playgroud)
Bru*_*ger 11
当 shell 获得如下命令行时:command > file.out
shell 本身打开(并可能创建)名为file.out
. shell 将文件描述符 0 设置为它从打开中获得的文件文件描述符。这就是 I/O 重定向的工作原理:每个进程都知道文件描述符 0、1 和 2。
难点在于如何打开file.out
. 大多数情况下,您希望file.out
在偏移量 0(即截断)处打开写入,这就是 shell 为您所做的。它截断了 .hgignore,将其打开以进行写入,将文件描述符复制为 0,然后执行 exec'ed head
。即时文件破坏。
在 bash shell 中,您可以执行 aset noclobber
来更改此行为。