ls 정렬이 영숫자가 아닌 문자를 무시하는 이유는 무엇입니까?


25

파일 이름을 정렬 할 때 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

2
UTF-8과 ASCII는 사용하고있는 모든 코드가 처음 128 개의 코드 포인트 (예 :) 인 경우 동일합니다. 그렇게하면 어떻게 LC_COLLATE=C ls됩니까?
Alexios

문제는 ASCII와 UTF-8이 동일하다는 것이 아니라 UTF-8에 자체 데이터 정렬 (정렬) 규칙이 있다는 것입니다.
다니엘 쿨만

1
예, [_-,.]그룹화되고 어떻게 든 반 무시되는 것이 사실입니다 . 간단하게, 그리고 만에 정렬 변경하기 때문에, 나는 그런 조합이 정의 정확히 어디에서 어떻게 모르겠지만, 그것은 정렬 문제가 될 수 있어야 C를 (통해하는 LC_COLLATE=C ls -l)이이 가정 (당신이 예상 정렬 순서를 제공하기 위해 충분 LC_ALL하다 무시하지 않음 LC_COLLATE). 이것은 유니 코드 베이직 다국어 플레인의 모든 문자 범위에 적용됩니다. 이것을 구현하는 예제 스크립트를 포함하도록 답변을 편집했습니다 ...
Peter.O

작동 방식이 마음에 들지 않으면 별칭을 만들어 ~ / .profile에 넣을 수 있습니다. alias ls = 'LC_COLLATE = C ls'</ kbd>
jippie

답변:


10

이것은 문자셋과 관련이 없습니다. 데이터 정렬 순서를 결정하는 언어입니다. libc는 $LC_COLLATE/ $LC_ALL/ 로 표시된 언어를 검사 $LANG하고 데이터 정렬 규칙 (예 : /usr/share/i18n/locales/*GLibC)을 조회하고 지시에 따라 텍스트를 정렬 합니다.


참고로 이보다 더 복잡합니다. strcoll예를 들어 하나를 사용한다면 aasa.c위와 같은 것이 정렬되어 있음을 알 수 있습니다 aas.c.
Don Scott

12

편집 : 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

2
그 문서는 어디에 있습니까? 이것이 유니 코드 표준의 일부입니까?
다니엘 쿨만

2
실제로, 그들은 같은 가치를 얻지 못합니다. 정렬 할 때 해당 문자는 무시됩니다. 값이 같은 것으로 취급되면 정렬 순서 a_1 a2 a_2가 불가능합니다.
다니엘 쿨만

노력과 샘플 코드 +1 여러 시간이 지나면 디렉토리 이름을 구두점으로 정렬하는 방식 tree이 일치 합니까? 비교 문자열에서 문장 부호가 제거되는 것과 같은 이야기가 더 있다고 생각합니다. /문자가 다른 순서와 상관없이 조합 순서에서 가장 낮은 문자로 설정되어야 한다고 말할 수 있습니다 .
WinEunuuchs2Unix
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.