为什么 ls 会这样对结果进行排序?

为什么 ls 会这样对结果进行排序?

我只是想知道为什么 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 终于成功了。

再次感谢您的快速而有用的回复。

相关内容