sort 是否支持就地对文件进行排序,例如“sed --in-place”?

sort 是否支持就地对文件进行排序,例如“sed --in-place”?

我是盲目的还是没有像--in-placefor这样的选择sort

为了将结果保存到输入文件中,sed 使用-i( --in-place)。

将输出重定向sort到输入文件

sort < f > f

结果使其变空。如果没有--in-place选择 - 也许有一些技巧可以做到这一点便利方式?

(我脑子里唯一想到的是:

sort < f > /tmp/f$$ ; cat /tmp/f$$ > f ; rm /tmp/f$$

搬家不是正确的选择,因为文件权限可能会改变。这就是为什么我用临时文件的内容覆盖然后将其删除。)

答案1

sort具有-o(或 --output) 选项,该选项将文件名作为参数。程序将数据写入临时文件,然后在排序完成后覆盖原始输入文件(只有在读取所有输入数据后才会发生这种情况)。 (这与所做的本质上是一样的sed -i。)

GNU sort信息页面:

    -o OUTPUT-FILE
    --output=OUTPUT-FILE
      将输出写入输出文件而不是标准输出。通常, sort在打开之前读取所有输入输出文件sort -o F F ,因此您可以使用和等命令安全地对文件进行排序cat F | sort -o F。然而,sortwith --merge( -m) 可以在读取所有输入之前打开输出文件,因此像这样的命令cat F | sort -m -o F - G并不安全,因为可能会在读取完成之前sort开始写入。Fcat

      在较新的系统上,如果设置了,则-o不能出现在输入文件之后 ,例如.可移植脚本应 在任何输入文件之前指定。POSIXLY_CORRECTsort F -o F-o OUTPUT-FILE

和来自The Open Group 基本规范第 7 期:

    -o output
      指定要使用的输出文件的名称,而不是标准输出。该文件可以与输入文件之一相同。
有报告称,sort如果磁盘空间不足或磁盘配额不足,或者sort写入输出文件时系统崩溃,或者发生其他错误,则可能会丢弃(即销毁)部分或全部数据。

简而言之,要就地对文件进行排序,可以使用以下命令:

sort -o filename filename

答案2

您可以使用sponge函数,首先浸泡stdin然后将其写入文件,例如:

sort < f | sponge f

其缺点sponge是它将输出临时存储在内存中,这对于大文件可能会出现问题。否则,您必须先将其写入文件,然后覆盖原始文件。

然而,正如其他答案所指出的那样,就地修改通常不是一个好主意,因为在进程(例如进程sponge)的中间,机器可能会崩溃,然后您可能会丢失原始文件和新文件。您最好先将其写入另一个文件,然后使用原子mv(移动)指令。

答案3

用输出文件覆盖输入文件是危险的,因为如果程序或系统在写入文件时崩溃,那么两者都会丢失。

一些程序(主要是 GNU 版本)具有就地选项(例如,-i在 perl 和 GNU sed 上;-o在 GNU sort 上)。他们的工作方式是将数据放入临时文件中,然后将其移动到位。

对于没有此选项的程序,科林·沃森的sponge效用(包括在Joey Hess 的 moreutils)为任何程序自动完成这项工作(示例:我可以cut就地更改文件吗?;如何使 iconv 用转换后的输出替换输入文件?)。但是,请注意,即使失败,也do_stuff | sponge myfile始终会覆盖,可能会出现空或不正确的输出:无法检测通过管道传输到其中的命令是否成功。因此,与使用临时文件相比,输入很方便,但不安全。myfiledo_stuffsponge

仅在极少数情况下,您无法使用相同的权限重新创建原始文件,我才建议就地覆盖该文件。在这种情况下,您最好将原始输入保存在某处。然后您可以简单地处理输入的副本并将其发送到原始文件中。

cp -p f ~/f.backup
sort <~/f.backup >|f
rm ~/f.backup # optional

答案4

使用-o或尝试 vim 方式:

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

相关内容