Ls

為什麼 ls 排序會忽略非字母數字字元?

  • December 25, 2019

對文件名進行排序時,ls忽略-,_. 我希望它也能在排序中使用這些字元。

一個例子:

touch a1 a2 a-1 a-2 a_1 a_2 a.1 a.2 a,1 a,2

現在顯示這些文件ls -1

a1
a_1
a-1
a,1
a.1
a2
a_2
a-2
a,2
a.2

我所期望的是這樣的:

a1
a2
a,1
a,2
a.1
a.2
a_1
a_2
a-1
a-2

即我希望在排序時考慮非字母數字字元。

誰能解釋這種行為?這種行為是由標準規定的嗎?或者這是因為編碼是 UTF-8?

**更新:**這似乎與 UTF-8 排序有關:

$ LC_COLLATE=C ls -1
a,1
a,2
a-1
a-2
a.1
a.2
a1
a2
a_1
a_2

這與字元集無關。相反,它是決定排序順序的語言。libc 檢查$LC_COLLATE/ $LC_ALL/中顯示的語言$LANG並查找其排序規則(例如/usr/share/i18n/locales/*,對於 GLibC)並按照指示對文本進行排序。

編輯:為使用 LC_COLLATE=C 排序的數據添加了測試


預設的整理順序是將這些“標點符號類型”字元視為具有相同的值..Use LC_COLLATE=C以程式碼點順序處理它們..

for i in 'a1' 'a_1' 'a-1' 'a,1' 'a.1' 'a2' 'a_2' 'a-2' 'a,2' 'a.2' ;do
 echo $i; 
done |LC_COLLATE=C sort

輸出

a,1
a,2
a-1
a-2
a.1
a.2
a1
a2
a_1
a_2

以下程式碼測試基本多語言平面中的所有有效UTF-8 字元(除了*\x00\x0a*;為簡單起見)

它將以已知(生成)升序順序的文件與隨機排序然後再次排序的文件進行比較LC_COLLATE=C。結果表明,C序列與原始生成的序列相同。

{ i=0 j=0 k=0 l=0
 for i in {0..9} {A..F} ;do
 for j in {0..9} {A..F} ;do
 for k in {0..9} {A..F} ;do
 for l in {0..9} {A..F} ;do
    (( 16#$i$j$k$l == 16#0000 )) && { printf '.' >&2; continue; }
    (( 16#$i$j$k$l == 16#000A )) && { printf '.' >&2; continue; }
    (( 16#$i$j$k$l >= 16#D800    && 
       16#$i$j$k$l <= 16#DFFF )) && { printf '.' >&2; continue; }
    (( 16#$i$j$k$l >= 16#FFFE )) && { printf '.' >&2; continue; }
    echo 0x"$i$j$k$l" |recode UTF-16BE/x4..UTF-8 || { echo "ERROR at codepoint $i$j$k$l " >&2; continue; } 
    echo 
 done
 done
 done; echo -n "$i$j$k$l " >&2
 done; echo >&2
} >listGen

            sort -R listGen    > listRandom
LC_COLLATE=C sort    listRandom > listCsort 

diff <(cat listGen;   echo "last line of listOrig " ) \
    <(cat listCsort; echo "last line of listCsort" )
echo 
cmp listGen listCsort; echo 'cmp $?='$?

輸出:

63485c63485
< last line of listOrig 
---
> last line of listCsort

cmp $?=0

引用自:https://unix.stackexchange.com/questions/35469