![为什么 ls 会这样对结果进行排序?](https://linux22.com/image/156282/%E4%B8%BA%E4%BB%80%E4%B9%88%20ls%20%E4%BC%9A%E8%BF%99%E6%A0%B7%E5%AF%B9%E7%BB%93%E6%9E%9C%E8%BF%9B%E8%A1%8C%E6%8E%92%E5%BA%8F%EF%BC%9F%20.png)
我只是想知道为什么 ls 输出按如下方式排序:
$ mkdir SortTest<br>
$ cd SortTest<br>
$ for a in {1..34}; do touch filename_$a.txt; done
$ ls -l
-rw-r--r-- 1 user user 0 Jun 28 10:49 filename_10.txt
-rw-r--r-- 1 user user 0 Jun 28 10:49 filename_11.txt
-rw-r--r-- 1 user user 0 Jun 28 10:49 filename_12.txt
-rw-r--r-- 1 user user 0 Jun 28 10:49 filename_13.txt
-rw-r--r-- 1 user user 0 Jun 28 10:49 filename_14.txt
-rw-r--r-- 1 user user 0 Jun 28 10:49 filename_15.txt
-rw-r--r-- 1 user user 0 Jun 28 10:49 filename_16.txt
-rw-r--r-- 1 user user 0 Jun 28 10:49 filename_17.txt
-rw-r--r-- 1 user user 0 Jun 28 10:49 filename_18.txt
-rw-r--r-- 1 user user 0 Jun 28 10:49 filename_19.txt
-rw-r--r-- 1 user user 0 Jun 28 10:49 filename_1.txt
-rw-r--r-- 1 user user 0 Jun 28 10:49 filename_20.txt
-rw-r--r-- 1 user user 0 Jun 28 10:49 filename_21.txt
-rw-r--r-- 1 user user 0 Jun 28 10:49 filename_22.txt
-rw-r--r-- 1 user user 0 Jun 28 10:49 filename_23.txt
-rw-r--r-- 1 user user 0 Jun 28 10:49 filename_24.txt
-rw-r--r-- 1 user user 0 Jun 28 10:49 filename_25.txt
-rw-r--r-- 1 user user 0 Jun 28 10:49 filename_26.txt
-rw-r--r-- 1 user user 0 Jun 28 10:49 filename_27.txt
-rw-r--r-- 1 user user 0 Jun 28 10:49 filename_28.txt
-rw-r--r-- 1 user user 0 Jun 28 10:49 filename_29.txt
-rw-r--r-- 1 user user 0 Jun 28 10:49 filename_2.txt
-rw-r--r-- 1 user user 0 Jun 28 10:49 filename_30.txt
-rw-r--r-- 1 user user 0 Jun 28 10:49 filename_31.txt
-rw-r--r-- 1 user user 0 Jun 28 10:49 filename_32.txt
-rw-r--r-- 1 user user 0 Jun 28 10:49 filename_33.txt
-rw-r--r-- 1 user user 0 Jun 28 10:49 filename_34.txt
-rw-r--r-- 1 user user 0 Jun 28 10:49 filename_3.txt
-rw-r--r-- 1 user user 0 Jun 28 10:49 filename_4.txt
-rw-r--r-- 1 user user 0 Jun 28 10:49 filename_5.txt
-rw-r--r-- 1 user user 0 Jun 28 10:49 filename_6.txt
-rw-r--r-- 1 user user 0 Jun 28 10:49 filename_7.txt
-rw-r--r-- 1 user user 0 Jun 28 10:49 filename_8.txt
-rw-r--r-- 1 user user 0 Jun 28 10:49 filename_9.txt
我从其他讨论中发现 ls -v 会产生一种更有用的方法。但这不会改变我期望的没有任何参数的输出,即:
(我期望什么,它如何不起作用,但为什么?)
-rw-r--r-- 1 user user 0 Jun 28 10:49 filename_1.txt
-rw-r--r-- 1 user user 0 Jun 28 10:49 filename_10.txt
-rw-r--r-- 1 user user 0 Jun 28 10:49 filename_11.txt
-rw-r--r-- 1 user user 0 Jun 28 10:49 filename_12.txt
-rw-r--r-- 1 user user 0 Jun 28 10:49 filename_13.txt
-rw-r--r-- 1 user user 0 Jun 28 10:49 filename_14.txt
-rw-r--r-- 1 user user 0 Jun 28 10:49 filename_15.txt
-rw-r--r-- 1 user user 0 Jun 28 10:49 filename_16.txt
-rw-r--r-- 1 user user 0 Jun 28 10:49 filename_17.txt
-rw-r--r-- 1 user user 0 Jun 28 10:49 filename_18.txt
-rw-r--r-- 1 user user 0 Jun 28 10:49 filename_19.txt
-rw-r--r-- 1 user user 0 Jun 28 10:49 filename_2.txt
-rw-r--r-- 1 user user 0 Jun 28 10:49 filename_20.txt
-rw-r--r-- 1 user user 0 Jun 28 10:49 filename_21.txt
-rw-r--r-- 1 user user 0 Jun 28 10:49 filename_22.txt
-rw-r--r-- 1 user user 0 Jun 28 10:49 filename_23.txt
-rw-r--r-- 1 user user 0 Jun 28 10:49 filename_24.txt
-rw-r--r-- 1 user user 0 Jun 28 10:49 filename_25.txt
-rw-r--r-- 1 user user 0 Jun 28 10:49 filename_26.txt
-rw-r--r-- 1 user user 0 Jun 28 10:49 filename_27.txt
-rw-r--r-- 1 user user 0 Jun 28 10:49 filename_28.txt
-rw-r--r-- 1 user user 0 Jun 28 10:49 filename_29.txt
-rw-r--r-- 1 user user 0 Jun 28 10:49 filename_3.txt
-rw-r--r-- 1 user user 0 Jun 28 10:49 filename_30.txt
-rw-r--r-- 1 user user 0 Jun 28 10:49 filename_31.txt
-rw-r--r-- 1 user user 0 Jun 28 10:49 filename_32.txt
-rw-r--r-- 1 user user 0 Jun 28 10:49 filename_33.txt
-rw-r--r-- 1 user user 0 Jun 28 10:49 filename_34.txt
-rw-r--r-- 1 user user 0 Jun 28 10:49 filename_4.txt
-rw-r--r-- 1 user user 0 Jun 28 10:49 filename_5.txt
-rw-r--r-- 1 user user 0 Jun 28 10:49 filename_6.txt
-rw-r--r-- 1 user user 0 Jun 28 10:49 filename_7.txt
-rw-r--r-- 1 user user 0 Jun 28 10:49 filename_8.txt
-rw-r--r-- 1 user user 0 Jun 28 10:49 filename_9.txt
我希望这是因为点“。”在 ASCII 表中位于 0..9 之前。即使排序应分别处理基本文件名和扩展名,filename_1 也比 filename_10 等短,因此应首先出现在排序字符串表中。
那么...为什么 ls 忽略所有这些并在 filename_10.txt 到 filename_19.txt 之后返回 filename_1.txt ?
有人知道吗?而且......一直都是这样,或者这是现代“改进”之一?如果是后者,我可以轻松地将其关闭吗?或者它实际上是 POSIX(或任何其他标准)的要求?
就我个人而言,我不喜欢计算机不遵循简单的规则,但其他人 - 即使这些可能被某些人认为“更用户友好” - 毕竟,它们更令人惊讶。
$ ls --version
ls (GNU coreutils) 8.30
答案1
感谢您的回复,这为我提供了有用的解释。
如果我理解正确的话:
现代系统往往有一些特定于语言的区域设置 - 如果没有手动设置为 LC_COLLATE=C,则遵循 LC_COLLATE
然而,这不仅改变了排序顺序以以特定于语言的“自然”方式处理大写/小写字母字符,而且同时导致忽略标点符号进行排序。
因此,filename_1.txt 会像 filename_1txt 一样进行排序,并出现在 filename_19txt 之后。
就我个人而言,我认为这是非常不自然的,并且是一种不需要的副作用,而不是一种改进。但它显然已经成为标准几年了。
更改 /etc/locale.conf 以包含 LC_COLLATE=C 应该会返回老式的、毫不奇怪的行为。
测试可以通过
$ LC_COLLATE=C; ls -l
这确实按照我的预期返回了列表。
PS:在我的 Devuan 系统上,/etc/locale.conf 不存在,尽管 man locale.conf 引用了它,并表示 systemd 会提前读取它,但仅仅创建该文件并放置一行 LC_COLLATE 是不够的=C 进入其中。也许是因为这里没有 systemd :-)
也无法通过 dpkg-reconfigure locales 设置 LC_COLLATE - 我在 /etc 下的任何现有文件中也找不到此设置
相反,我添加了这一行
export LC_COLLATE=C
进入 ~/.bashrc 终于成功了。
再次感谢您的快速而有用的回复。