ls 默认排序不一致

iob*_*der 0 ls sort

为什么在文件名末尾添加相同的字符会改变排序顺序,如下所示?在任何正常的字符串比较方法中,如果将相同的字符串添加到两个字符串的末尾,我希望两个字符串的比较不会有所不同。

$ type ls
ls is aliased to `ls --color=auto`
$ touch I II III IV V VI
$ ls
I  II  III  IV  V  VI
$ rm -f *
$ for n in I II III IV V VI; do touch "$n x"; done
$ ls 
III x  II x  IV x  I x  VI x  V x
Run Code Online (Sandbox Code Playgroud)

虽然 Python 的工作方式如我所料:

>>> ns = ['I', 'II', 'III', 'IV', 'V', 'VI']
>>> sorted(ns)
['I', 'II', 'III', 'IV', 'V', 'VI']
>>> sorted(n + ' x' for n in ns)
['I x', 'II x', 'III x', 'IV x', 'V x', 'VI x']
>>> 
Run Code Online (Sandbox Code Playgroud)

小智 7

正如 cyrus 的评论所暗示的那样,原因是整理规则(=locale-aware string比较)。在您的情况下,对于大多数非 C/POSIX 语言环境(例如“en_US.UTF-8”),在比较字符串时会忽略空格字符,因此“Ix”和“I x”被评估为相等,因此, “II”在“Ix”之前。

请参阅以下内容:

$ touch I "I x" "Ix" "II" IIx "II x"
Run Code Online (Sandbox Code Playgroud)

使用非 C 语言环境时,比较字符串时通常会忽略空格:

$ locale | grep LANG
LANG=en_US.UTF-8
LANGUAGE=en_US

$ ls -lhog
total 0
-rw-rw-r-- 1 0 Dec 26 17:12 I
-rw-rw-r-- 1 0 Dec 26 17:12 II
-rw-rw-r-- 1 0 Dec 26 17:12 IIx
-rw-rw-r-- 1 0 Dec 26 17:12 II x
-rw-rw-r-- 1 0 Dec 26 17:12 Ix
-rw-rw-r-- 1 0 Dec 26 17:12 I x
Run Code Online (Sandbox Code Playgroud)

强制使用 POSIX/C 语言环境,文件名通过 ASCII 字符进行比较,因此“空格”字符位于“x”或“I”之前:

$ LC_ALL=C ls -lhog
total 0
-rw-rw-r-- 1 0 Dec 26 17:12 I
-rw-rw-r-- 1 0 Dec 26 17:12 I x
-rw-rw-r-- 1 0 Dec 26 17:12 II
-rw-rw-r-- 1 0 Dec 26 17:12 II x
-rw-rw-r-- 1 0 Dec 26 17:12 IIx
-rw-rw-r-- 1 0 Dec 26 17:12 Ix
Run Code Online (Sandbox Code Playgroud)

要查看实际的比较函数结果 ( strcoll(3)),请ltrace像这样使用:

$ LC_ALL=C ltrace -e strcoll ls -lhog
ls->strcoll("I", "II x")       = -73
ls->strcoll("Ix", "I")         = 120
ls->strcoll("Ix", "II x")      = 47
ls->strcoll("I x", "II")       = -41
ls->strcoll("IIx", "I x")      = 41
ls->strcoll("IIx", "II")       = 120
ls->strcoll("I x", "I")        = 32
ls->strcoll("I x", "II x")     = -41
ls->strcoll("II", "II x")      = -32
ls->strcoll("IIx", "II x")     = 88
ls->strcoll("IIx", "Ix")       = -47
total 0
-rw-rw-r-- 1 0 Dec 26 17:12 I
-rw-rw-r-- 1 0 Dec 26 17:12 I x
-rw-rw-r-- 1 0 Dec 26 17:12 II
-rw-rw-r-- 1 0 Dec 26 17:12 II x
-rw-rw-r-- 1 0 Dec 26 17:12 IIx
-rw-rw-r-- 1 0 Dec 26 17:12 Ix
+++ exited (status 0) +++

$ LC_ALL=en_US.UTF-8 ltrace -e strcoll ls -lhog
ls->strcoll("I", "II x")       = -1
ls->strcoll("Ix", "I")         = 1
ls->strcoll("Ix", "II x")      = 15
ls->strcoll("I x", "II")       = 15
ls->strcoll("IIx", "II")       = 1
ls->strcoll("IIx", "I x")      = -15
ls->strcoll("II", "I")         = 1
ls->strcoll("II", "II x")      = -1
ls->strcoll("IIx", "II x")     = -1
ls->strcoll("I x", "II x")     = 15
ls->strcoll("I x", "Ix")       = 1
total 0
-rw-rw-r-- 1 0 Dec 26 17:12 I
-rw-rw-r-- 1 0 Dec 26 17:12 II
-rw-rw-r-- 1 0 Dec 26 17:12 IIx
-rw-rw-r-- 1 0 Dec 26 17:12 II x
-rw-rw-r-- 1 0 Dec 26 17:12 Ix
-rw-rw-r-- 1 0 Dec 26 17:12 I x
+++ exited (status 0) +++
Run Code Online (Sandbox Code Playgroud)