想请教一个关于 Bash 管道符和 tee 的问题

32次阅读

共计 672 个字符,预计需要花费 2 分钟才能阅读完成。

问题

v2 大佬比较多,想在这里请教各位大佬一个困惑了我多年的问题: 如何在一行命令里,排序文件内容并用 tee 写到原来的文件中?

使用临时文件

想要将 foo.txt 文件中的文本排序后依然保存到 foo.txt 文件中,需要先写到一个临时文件,然后将临时文件重命名为 foo.txt。这也是一个比较常见的方案。

sort foo.txt | tee tmp-foo.txt
mv tmp-foo.txt foo.txt

我一直以来都以为 tee 无法直接回写(不知道这个词用的对不对)到文件,如果直接 sort foo.txt | tee foo.txt,那么 foo.txt 的内容会是空的。

tee 有时可以直接回写文件

但是最近我发现并不是这样,有时是可以回写成功的。文件足够小时有很大概率可以直接回写,比如下图可以看到回写成功了两次。而稍微大点的文件就比较难

想请教一个关于 Bash 管道符和 tee 的问题

和朋友们的讨论

在 v2 上发帖提问之前,我和同事、朋友们讨论过这个问题,我们有了一点点进展。

我们认为,没有回写成功,可能是因为文件还没读完就去写入。因此可以让写入晚一点,比如加一个 sleep,这样确实可以解决,也是目前为止唯一的解决方案。

sort foo.txt | {sleep 1; tee foo.txt;}

这样听起来很合理,但是我们还是不理解为什么有时没有读完

  1. 我用 strace 分析过回写成功和失败的日志,没有发现任何区别。
  2. sort 命令是在内存中排序,读取速度和硬件性能有关,但是内存频率高、性能好、读的快,就可以成功写入,这也太不稳定了。
  3. 这可能和 Bash 管道的实现有关吗?如果还没有执行完管道符前的命令,就去执行管道符后的命令了,听起来不太合理。
正文完
 0