sort file > file 后文件变空:重定向先截断了输入
sort file > file 导致输入变空时,先保留现场和备份;改用独立输出,或在普通 GNU sort 模式使用 -o,并核对原地写入风险。
想把文件原地排序,执行 sort file > file 后,却发现文件变成零字节。问题发生在 sort 读取数据之前:shell 为 > 打开输出文件,并截断已有内容,随后才启动 sort。程序打开同一个路径时,原数据已经没有了。
这个结果不能通过升级 sort、加 sudo 或再次执行命令恢复。先停止对目标文件的写入,确认是否有备份、快照或可重新生成的数据。下面的修正用于仍有完整输入副本的后续处理,不会找回已经被截断的内容。
先确认是真空文件,还是开头出现空行
使用文件属性或字节数检查,而不只是打开编辑器看第一屏。例如:
wc -c -- ./data.txt
data.txt 是示例路径。零字节说明没有内容;非零但开头空白,可能是原来的空行排序到前面,也可能是其他输出变化,应继续检查副本。不要把所有“看起来空了”都归因于截断。
两个不同文件名也可能通过符号链接或硬链接指向同一文件。输入和输出名字不同,仍要确认它们没有这种关系;仅在文本层换个路径拼写,不能保证输出独立。
优先把排序结果写入未占用的新文件
保留完整输入和备份,选择一个确认不存在、也没有链接回输入的新输出路径:
sort -- ./data.txt > ./data.sorted-check.txt
这一条只演示普通按行排序。原任务如果有数值、字段或 locale 要求,应保留对应排序规则;改变输出路径不应该顺便改变排序意义。输出文件所在目录要有写入空间和合适权限,内容敏感时按原数据的访问策略控制。
> 同样会截断已经存在的结果文件,所以执行前确认新路径,不能把示例名字当作永远可覆盖的临时文件。检查命令退出状态、结果内容及所需排序规则,失败或磁盘不足时保留原输入,不要用半份结果替换它。
结果确认后,再通过项目已有文件替换流程更新正式数据。替换还可能影响权限、所有者、链接关系或正在读取它的程序;需要保留这些属性时应在维护流程中明确处理。不要把一个跨文件系统的移动假定为可保证原子完成的切换。
GNU sort 的 -o 可以原地输出,但仍需备份
确认使用 GNU sort、输入完整,且确实要普通原地排序时,可使用它自己的输出选项:
sort -o ./data.txt -- ./data.txt
这里没有 shell 的 > ./data.txt。正常排序模式下,GNU sort 在打开输出前会读取所有输入,因此支持这种用法。把 -o 放在输入之前,也能避免某些环境下选项位置带来的兼容问题。
不过,原地排序不是抗崩溃的数据事务。磁盘 I/O 错误、程序异常或系统中断仍可能损失内容,重要数据更适合先写新文件再检查。操作时也不能有其他进程同时改输入,否则结果无法视为固定输入的一次可靠排序。
不要把这条规则扩大到所有工具或所有 sort 模式。-m 是合并已排序输入,可能在读完全部输入前打开输出;管道中的读取进程也可能尚未读完原文件。将这类流程改成同文件 -o,不能直接套用普通排序的判断,应使用独立输出。
追加输出也不是修复
把 > 换成 >> 只是改成追加:它不会把原内容替换成排序结果,还可能在读写同一文件时形成不可预期的数据增长。不要尝试用这种办法保存原文件。
shell 的防覆盖设置可以阻止部分已有普通文件的 > 写入,但它不是恢复工具,也不能替代对链接、输出路径和其他程序写入行为的检查。若此次输入已归零,应从确认可用的备份恢复到独立位置,核对数据后再处理。
验收要同时确认完整输入已保留、输出符合原排序要求,以及正式消费者读取到正确版本。普通排序可能补齐最后的换行;添加去重或筛选选项也会改变内容数量,不宜只凭字节数相同就宣布数据完整。需要回退时恢复事先保留的文件及属性,不能再次排序空文件来尝试找回数据。


