为什么命令 shuf file > file 会留下一个空文件,而类似的命令却不会?

tor*_*yan 9 shell pipe io-redirection

我知道这是另一个问题的重复(为什么这个排序命令给我一个空文件?)但我想扩展这个问题以回应给出的答案。

命令

shuf example.txt > example.txt

返回一个空白文件,因为 shell 在对文件进行 shuffle 之前将其截断,只留下一个空白文件进行 shuffle。然而,

cat example.txt | shuf > example.txt

将按预期生成一个混洗的文件。

当简单重定向不起作用时,为什么管道方法起作用?如果文件在命令运行之前被截断,第二种方法不应该也留下一个空文件吗?

fro*_*utz 21

问题是> example.txtshuf example.txt开始读取该文件之前开始写入该文件。所以由于还没有输出,example.txt是空的,shuf读取一个空文件,并且shuf在这种情况下没有输出,最终结果保持为空。

您的其他命令可能会遇到同样的问题。> example.txt可能会在cat example.txt开始读取文件之前杀死文件;这取决于 shell 执行这些事情的顺序,以及cat实际打开文件需要多长时间。

为了完全避免此类问题,您可以使用shuf example.txt > example.txt.shuf && mv example.txt.shuf example.txt.

或者你可以一起去shuf example.txt --output=example.txt

  • `> example.txt` 不会开始写入文件,它会打开文件进行截断写入。与 `1<> example.txt` 相比,它以读写方式打开而不被截断。 (2认同)
  • 你的措辞令人困惑。`> file` 不_写_任何东西,真正的问题是它会被截断。如果它只是为了写入而打开(就像 `1<> file` 那样),就不会有任何问题(至少对于 `shuf` 不会)。 (2认同)

Tim*_*imo 9

moreutils有一个命令sponge

   sponge  reads  standard input and writes it out to the specified file.
   Unlike a shell redirect, sponge soaks up all its input before  opening
   the output file. This allows constricting pipelines that read from and
   write to the same file.
Run Code Online (Sandbox Code Playgroud)

用这种方式你可以做到:

shuf example.txt | sponge example.txt
Run Code Online (Sandbox Code Playgroud)

不幸的是,moreutils 包也有一个名为 util 的工具parallel,它远不如 gnu parallel 有用。我删除了parallel由 moreutils 安装的


归档时间:

查看次数:

11889 次

最近记录:

8 年,2 月 前