shell 重定向位置的区别

shell difference between redirect position

这两行有区别吗?

for i in $(seq 1 10); do echo $i - `date`; sleep 1; done >> /tmp/output.txt

for i in $(seq 1 10); do echo $i - `date` >> /tmp/output.txt ; sleep 1; done

因为 Robert told me 第一个只在 for 循环之外生成 I/O OP。

但是,如果我输入 tail -f /tmp/output.txt,其行为方式完全相同。

如果他们成功了,他们也会这样做。但是,如果它们因任何原因失败,可能会有显着差异。

第一个:

for ...; do
   # things
done >> file

这将在循环完成后重定向到文件。但是,只要 Bash 决定刷新缓冲区,它就可能发生。

想象一下在第 3 次迭代后出现故障:您无法判断文件中存储了哪些内容。

第二个:

for ...; do
   # things >> file
done

这将在每次迭代时重定向到该文件。

假设在第 3 次迭代后出现问题:您确定前两个循环已正确存储在文件中。

来自How to redirect output from an infinite-loop program

If your program is using the standard output functions (e.g. puts, printf and friends from stdio.h in C, cout << … in C++, print in many high-level languages), then its output is buffered: characters accumulate in a memory zone which is called a buffer; when there's too much data in the buffer, the contents of the buffer is printed (it's “flushed”) and the buffer becomes empty (ready to be filled again). If your program doesn't produce much output, it may not have filled its buffer yet.

此外,来自 the answer you link

Placing the redirection operator outside the loop doubles the performance when writing 500000 lines (on my system).

这是有道理的:如果你必须在每个循环中刷新,那么它比让 Bash 在觉得方便的时候刷新要花费更多的时间。一次写五行比一次写一行容易

还有一个没有提到的重要区别:>> 每次都打开文件进行写入。这会显着影响性能。

此外,如果 /tmp/output.txt 在循环 运行 时被删除,echo ... >> /tmp/output.txt 将使用新内容重新创建文件,而 for ... done >> /tmp/output.txt 将继续添加数据到同一个文件。

记住这一点很重要,尤其是当我们处理硬链接或临时文件时(通常,我们会在创建临时文件后立即取消链接,以避免在 Bash 脚本退出时出现过时文件没想到)。