Answers:
使用时>
,该文件以截断模式打开,因此在命令尝试读取该文件之前,将其内容删除。
使用时>>
,文件将以追加模式打开,因此将保留现有数据。但是,在这种情况下,使用相同的文件作为输入和输出仍然很冒险。如果文件足够大,无法容纳读取的输入缓冲区大小,则文件大小可能会无限期增长,直到文件系统已满(或达到磁盘配额)为止。
如果要使用不支持就地修改的命令将文件用作输入和输出,则可以使用以下两种解决方法:
仅在运行实用程序时未发生错误的情况下,使用中间文件并覆盖原始文件(这是最安全,更常见的方法)。
fold foo.txt > fold.txt.$$ && mv fold.txt.$$ foo.txt
如果发生错误或中断,请避免使用中间文件,否则可能会丢失部分或全部数据。在此示例中,在删除文件之前,将的内容foo.txt
作为输入传递到子shell(括号内)。前一个inode保持活动状态,因为子shell在读取数据时保持其打开状态。内部实用程序(此处为)写入的文件,名称相同(fold
foo.txt
)指向不同的inode,因为已删除了旧目录条目,因此从技术上讲,在此过程中有两个具有相同名称的不同“文件”。当子shell结束时,旧的inode被释放并且其数据丢失。注意确保您有足够的空间来同时临时存储旧文件和新文件,否则会丢失数据。
(rm foo.txt; fold > foo.txt) < foo.txt
在应用程序有机会读取文件之前,外壳程序会打开该文件以进行写入。打开文件以将其截断。
在bash中,流重定向操作符在评估左操作数之前先... > foo.txt
清空。foo.txt
一个人可能使用命令替换并将其结果打印为一种解决方法。与其他答案相比,此解决方案所需的其他字符更少:
printf "%s\n" "$(less foo.txt)" > foo.txt
注意:此命令不会保留中的任何尾随换行符foo.txt
。在下面的评论部分中查看更多信息
在此,子外壳$(...)
程序在流重定向操作符之前进行评估>
,因此可以保留信息。
tmp=$(cmd; printf q); printf '%s' "${tmp%q}"
。但是您错过了这个答案的另一个问题:当它表示“命令替换”时,它会显示“ subshell”。是的,命令替换通常是子外壳程序,反之亦然,子外壳程序通常对于此问题没有帮助。