【问题标题】:How do I update a file using commands run against the same file?如何使用针对同一文件运行的命令更新文件?
【发布时间】:2015-03-15 17:17:01
【问题描述】:

作为一个简单的例子,考虑以下命令:

$ sort file.txt 

这将按排序顺序输出文件的数据。如何将这些数据直接放回同一个文件中?我想用排序结果更新文件。

这不是解决方案:

$ sort file.txt > file.txt

... 因为它会导致文件出现空白。有没有办法在不创建临时文件的情况下更新这个文件?

当然,我可以这样做:

sort file.txt > temp.txt; mv temp.txt file.txt 

但我宁愿将结果保存在内存中,直到处理完成,然后将它们写回同一个文件。 sort 实际上有一个标志可以让这成为可能:

sort file.txt -o file.txt

...但我正在寻找一种不依赖于具有特殊标志的二进制文件来解决此问题的解决方案,因为并非所有都可以保证。是否有某种 linux 命令可以保存数据直到处理完成?

【问题讨论】:

  • 你知道mv 真的是重命名,对吧?使用临时文件的好处是当你的机器在sort中间崩溃时不会导致问题(例如)。
  • @rici 是的,mv 为我覆盖了文件。这模拟更新文件。无论如何,我正在寻找不需要中间文件的解决方案。
  • mv 不会覆盖文件。它只是重命名它。当然,确实有一段时间两个文件同时存在,但假设数据可以放入内存,这可能不会对您的磁盘造成太大负担。事实上,许多声称“就地”工作的实用程序(包括 sed)实际上使用临时文件,既安全又简单。

标签: linux shell command pipe in-place


【解决方案1】:

对于排序,您可以使用-o 选项。

对于更通用的解决方案,您可以使用 moreutils 包中的sponge

sort file.txt | sponge file.txt

如下所述,这里的错误处理很棘手。如果sponge 之前的步骤出现问题,您可能会得到一个空文件。

这是这个问题的副本,讨论了上面的解决方案:How do I execute any command editing its file (argument) "in place" using bash?

【讨论】:

  • 谢谢,我没有注意到 sort 也有一个标志来处理这个问题。我仍在寻找一种解决方案,该解决方案可以与没有这些特殊标志的程序一起工作,以考虑重写到同一个文件。
  • @TrevorHickey - 尝试问题中提供的海绵解决方案 - 它应该可以满足您的需求。基本上,对文件进行操作,将输出通过管道传输到sponge file,就完成了。
  • sort file.txt | sponge file.txt
  • @angie: edit 你的答案并在此处添加sponge。注意:如果出现错误,输入文件可能不完整,例如为空。
【解决方案2】:

您可以使用sed(使用其r command)和Process Substitution

sed -ni r<(sort file) file

这样,你告诉sed不要打印(原始)行(-n option)并附加&lt;(sort file)生成的文件。
众所周知的-i option 就是其中之一。

示例

$ cat file
b
d
c
a
e
$ sed -ni r<(sort file) file
$ cat file
a
b
c
d
e

【讨论】:

  • +1 非常有创意地使用 sed。不是每个人都需要备份文件。对于 GNU sed,与 BSD sed 不同,这可以通过简单地从命令中省略 .bak 来完成。
【解决方案3】:

试试 vim 方式:

$ ex -s +'%!sort' -cxa file.txt

【讨论】:

    猜你喜欢
    • 2017-04-18
    • 1970-01-01
    • 1970-01-01
    • 2012-12-06
    • 1970-01-01
    • 2017-06-13
    • 2018-03-30
    • 2021-01-29
    相关资源
    最近更新 更多