总结

总结

考虑像 Bash 或 sh 这样的 shell。>和之间的基本区别>>体现在目标文件存在的情况下:

  • >将文件截断为零大小,然后写入;
  • >>不会截断,它会写入(附加)到文件末尾。

如果文件不存在,则创建文件并将其大小设为零,然后写入。对于这两个运算符来说都是如此。当目标文件尚不存在时,这两个运算符似乎是等效的。

真的是这样吗?

答案1

总结

本质>>上是“始终寻找文件末尾”,同时>保持指向最后写入位置的指针。


完整答案

(注意:我所有的测试都是在 Debian GNU/Linux 9 上完成的)。

另一个区别

不,它们不等同。其他差异。无论目标文件之前是否存在,它都可能表现出来。

>为了观察它,运行一个生成数据并重定向到带有或 的文件的进程>>(例如pv -L 10k /dev/urandom > blob)。让它运行并更改文件的大小(例如truncate)。您将看到>保持其(不断增长的)偏移量,而>>始终附加到末尾。

  • 如果将文件截断为较小的尺寸(可以是零尺寸)
    • >不会在意,它会像什么都没发生一样在其所需的偏移量处写入;截断后偏移量超出了文件的末尾,这将导致文件恢复其旧大小并进一步增长,丢失的数据将用零填充(如果可能的话,以稀疏的方式);
    • >>将附加到新的末尾,文件将从其截断的大小开始增长。
  • 如果你放大文件
    • >不会在意,它会像什么都没发生一样在其所需的偏移量处写入;只需改变文件大小后偏移量就在文件内部的某个地方,这将导致文件停止增长一段时间,直到偏移量到达新的末尾,然后文件就会正常增长;
    • >>将附加到新的末尾,文件将从其扩大的大小开始增长。

另一个示例是在数据生成过程运行并写入文件时附加(使用单独的>>)一些额外内容。这类似于扩大文件。

  • 生成过程>将在其所需的偏移量处写入并最终覆盖多余的数据。
  • 生成过程>>将跳过新数据并将其附加到后面(可能会发生竞争条件,两个流可能会交错,但仍然不会覆盖任何数据)。

例子

在实践中这有关系吗?这个问题

我正在运行一个在 stdout 上产生大量输出的进程。将其全部发送到文件 [...] 我可以使用某种日志轮换程序吗?

这个答案说解决方案是logrotate使用copytruncate如下选项:

创建副本后截断原始日志文件,而不是移动旧日志文件并选择性地创建新日志文件。

根据我上面所写,重定向>将立即使截断的日志变大。稀疏性将挽救局面,不会浪费大量磁盘空间。然而,每个连续的日志中将有越来越多的前导零,而这些零是完全不必要的。

但是,如果logrotate创建副本时不保留稀疏性,那么每次复制时这些前导零将需要越来越多的磁盘空间。我还没有调查过该工具的行为,它可能足够智能,可以动态处理稀疏性或压缩(如果启用了压缩)。然而,这些零可能只会造成麻烦,或者充其量是中性的;它们没有什么好处。

在这种情况下,使用>>而不是>会更好得多,即使目标文件即将被创建。


表现

我们可以看到,这两个操作符不仅在开始时表现不同,而且在之后也不同。这可能会导致一些(微妙的?)性能差异。目前我没有有意义的测试结果来支持或反驳这一点,但我认为你不应该自动假设它们的性能总体上是相同的。

相关内容