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_1.txt를 filename_19.txt로 반환합니까?

아는 사람 있나요? 그리고... 항상 이랬나요, 아니면 이것이 현대의 "개선 사항" 중 하나인가요? 후자라면 쉽게 끌 수 있나요? 아니면 실제로 POSIX(또는 다른 표준)의 요구 사항입니까?

개인적으로 나는 단순한 규칙을 따르지 않는 컴퓨터를 좋아하지 않지만, 어떤 사람들은 이것이 "더 사용자 친화적"이라고 생각할지라도 결국 더 놀라운 컴퓨터를 좋아하지 않습니다.

$ ls --version
ls (GNU coreutils) 8.30

답변1

답장을 보내 주셔서 감사합니다. 유용한 설명을 제공했습니다.

내가 올바르게 이해했다면:

최신 시스템은 언어별 로케일을 갖는 경향이 있습니다. 수동으로 LC_COLLATE=C로 설정하지 않은 경우 LC_COLLATE를 따릅니다.

그러나 이로 인해 대문자/소문자 알파벳 문자를 언어별 "자연스러운" 방식으로 처리하도록 정렬 순서가 변경될 뿐만 아니라 정렬 시 구두점이 무시됩니다.

따라서 filename_1.txt는 filename_1txt와 같이 정렬되며 filename_19txt 뒤에 나타납니다.

개인적으로 이는 개선이라기보다는 매우 부자연스럽고 원치 않는 부작용이라고 생각합니다. 그러나 그것은 몇 년 동안 표준이 된 것 같습니다.

LC_COLLATE=C를 포함하도록 /etc/locale.conf를 변경하면 구식의 놀라운 동작이 반환되어야 합니다.

테스트는 통과할 수 있다

$ LC_COLLATE=C; ls -l

예상대로 목록이 반환됩니다.

추신: 내 Devuan 시스템에는 /etc/locale.conf가 존재하지 않으며 man locale.conf가 이를 참조하고 systemd가 이를 미리 읽을 것이라고 말하지만 파일을 생성하고 LC_COLLATE 줄을 넣는 것만으로는 충분하지 않습니다. =C 들어가세요. 아마도 여기에는 시스템이 없기 때문일 것입니다 :-)

dpkg-reconfigure 로케일을 통해 LC_COLLATE를 설정할 수도 없습니다. /etc 아래의 기존 파일에서도 이 설정을 찾을 수 없습니다.

대신에 다음 줄을 추가했습니다.

export LC_COLLATE=C

~/.bashrc 입력이 마침내 성공했습니다.

빠르고 유용한 답변에 다시 한번 감사드립니다.

관련 정보