为什么将文件的输出重定向到自身会产生一个空白文件?

see*_*ker 21 unix bash unix-utils

为什么将文件的输出重定向到自身会产生一个空白文件?

在 Bash 中说明,为什么

less foo.txt > foo.txt
Run Code Online (Sandbox Code Playgroud)

fold foo.txt > foo.txt
Run Code Online (Sandbox Code Playgroud)

产生空foo.txt?由于诸如此类的附加less eggs.py >> eggs.py会生成 中文本的两个副本,因此eggs.py人们可能会期望覆盖会生成文本的一个副本。

请注意,我并不是说这是一个错误,它更可能是指向有关 Unix 的深层内容的指针。

jll*_*gre 22

使用 时>,文件以截断模式打开,因此在命令尝试读取它之前删除其内容。

使用 时>>,文件以追加模式打开,以便保留现有数据。然而,在这种情况下使用相同的文件作为输入和输出仍然是相当危险的。如果文件大到无法容纳读取输入缓冲区的大小,则其大小可能会无限增长,直到文件系统已满(或达到磁盘配额)。

如果您想使用不支持就地修改的命令将文件用作输入和输出,您可以使用以下几种解决方法:

  • 使用中间文件并在完成后覆盖原始文件,并且仅当运行该实用程序时没有发生错误(这是最安全和更常见的方法)。

    fold foo.txt > fold.txt.$$ && mv fold.txt.$$ foo.txt
    
    Run Code Online (Sandbox Code Playgroud)
  • 避免使用中间文件,代价是在发生错误或中断时可能会丢失部分或全部数据。在这个例子中,在删除文件之前, 的内容foo.txt作为输入传递给子shell(在括号内)。前一个 inode 保持活动状态,因为 subshel​​l 在读取数据时保持打开状态。由内部实用程序(此处)写入但具有相同名称的文件(foldfoo.txt) 指向不同的 inode,因为旧的目录条目在技术上已被删除,因此在此过程中有两个不同的同名“文件”。当子shell结束时,旧的inode被释放并且它的数据丢失。请注意确保您有足够的空间同时临时存储旧文件和新文件,否则您将丢失数据。

    (rm foo.txt; fold > foo.txt) < foo.txt
    
    Run Code Online (Sandbox Code Playgroud)

  • 来自 [moreutils](http://joeyh.name/code/moreutils/) 的 `sponge` 也可以提供帮助。`折叠foo.txt | 海绵 foo.txt` – 或 `fold foo.txt | 海绵 !$` 也应该这样做。 (4认同)

Ign*_*ams 7

在应用程序有机会读取文件之前,shell 将打开该文件以供写入。打开文件进行写入会截断它。