Bash中如何对含数字的文件名实现符合预期的通用自然排序
问题说明
现有存储文件名的文本文件mylist.txt,执行cat mylist.txt查看原始内容:
myfile.txt myfile.version2.txt myfile.version.tab.txt
使用Python内置sorted()对列表做默认字典序排序时,输出符合预期:
myfile.txt myfile.version.tab.txt myfile.version2.txt
但在Bash环境中执行cat mylist.txt | sort或cat mylist.txt | sort -V,得到的结果均为:
myfile.txt myfile.version2.txt myfile.version.tab.txt
和预期排序结果不符。后续文件名列表还可能新增myfile.version.tab2.txt、myfile.version.tab.txt这类命名,需要通用方案实现和Python默认排序完全一致的效果。
原因分析
Bash下sort默认排序规则受当前系统locale(本地化配置)影响,多数用户的系统默认locale会调整标点、字符的排序优先级,不会严格按ASCII字节序比较;而sort -V是版本排序逻辑,会主动拆分字符串中的数字段按数值比较,优先级高于普通字符串段,因此会出现version2排在version.tab前的结果。
通用解决方案
强制sort使用C locale执行排序,即可完全对齐Python默认的ASCII字典序排序逻辑,命令如下:
LC_ALL=C sort mylist.txt
注:该写法无需额外调用
cat做管道传递,直接读取文件排序,执行效率更高。
效果验证
- 对原始3个文件名的列表执行命令,输出:
myfile.txt myfile.version.tab.txt myfile.version2.txt
和Pythonsorted()结果完全一致。
2. 对包含myfile.version.tab2.txt、myfile.version.tab.txt的扩展列表执行命令,输出:
myfile.version.tab.txt myfile.version.tab2.txt
同样符合预期。
方案说明
- 兼容性极强:
LC_ALL=C是POSIX标准定义的环境变量,所有类Unix系统(Linux、macOS、BSD等)均支持,不会因为sort版本、系统配置差异出现排序结果不一致的问题。 - 逻辑完全对齐:C locale下字符比较严格按ASCII字节值执行,和Python 3默认字符串按Unicode码点比较ASCII段文件名的逻辑完全一致,不会出现规则偏差。
- 扩展场景:如果需要直接排序当前目录下的文件,直接执行
LC_ALL=C ls -1即可得到和Python遍历目录后排序完全相同的列表。
内容的提问来源于stack exchange,提问作者e8e504671f
相关产品推荐
相关产品推荐

