터미널이나 Perl에서 사용할 때 와일드카드 결과의 순서가 다를 수 있는 이유는 무엇입니까?

터미널이나 Perl에서 사용할 때 와일드카드 결과의 순서가 다를 수 있는 이유는 무엇입니까?

다음과 같은 와일드카드와 함께 ls를 사용하여 파일을 나열하는 여러 파일과 Perl 스크립트가 있는 폴더가 있습니다.

#!/usr/bin/perl
system("ls -U -1 dir/*");

bash 터미널에서 정확히 동일한 명령을 실행하면 동일한 결과를 얻을 수 있지만 순서가 다르다는 것을 알았습니다.

왜 그럴까요? 두 컨텍스트 모두에서 와일드카드가 다르게 처리됩니까?

예:

mkdir dir
touch dir/a_0 dir/a1_0

터미널 출력:

dir/a_0
dir/a1_0

펄 출력:

dir/a1_0
dir/a_0

답변1

Perl의 기능은 일반적으로 프로세스를 분기하고 하위 프로세스에서 인수로 system("cmd")시스템의 쉘(일반적으로 )을 실행하여 해당 쉘 명령줄을 구문 분석하고 실행합니다 ./bin/sh["sh", "-c", "cmd"]sh

최적화로서 공백과 탭 이외의 쉘 메타 문자(예: 인용 문자 또는 글로빙 문자 또는 ...와 같은 것)가 포함되지 않은 경우 쉘 호출 없이도 수행될 수 있지만 여기에는 쉘 메타가 있습니다 cmd. -문자가 있기 때문에 .;&&*

따라서 이는 ls -U -1 dir/*시스템의 쉘에 의해 해석됩니다.

dir/*에 전달된 일치하는 파일 목록을 확장하는 것은 셸이므로 ls수행 방법은 셸에 따라 다릅니다.

터미널에서는 일반적으로 로그인 셸을 실행하지만 일반적으로 /bin/sh. 또한 (피터프가 언급한), 해당 셸은 대화형으로 실행되므로 일반적으로 일부 설정이 글로빙 수행 방법에 영향을 미칠 수 있는 구성 파일을 읽습니다 ~/.zshrc(셸이 ).zsh

예를 들어:

내 쉘은 이고 , 내 에는 zsha가 있으므로 다음과 같습니다.setopt dotglob~/.zshrc

$ echo *
.a d é f

다음 내용을 읽지 않고 ~/.zshrc:

$ zsh -c 'echo *'
d é f
$ LC_ALL=C zsh -c 'echo *'
d f é

zsh목록을 정렬할 때 로케일을 존중한다는 것을 알 수 있습니다 .

$ sh -c 'echo *'
d f é

sh(제 경우에는 Debian 입니다 ash) 로케일을 따르지 않고 C 로케일처럼 정렬합니다.

특정 쉘로 명령줄을 해석하려면 다음과 같이 작성할 수 있습니다 perl.system()

system("zsh", "-c", "cmd");

하나 이상의 인수가 전달되면 perl'은 (는 system()) 암시적으로 쉘을 호출하지 않으므로 위에서는 인수 /bin/zsh로 실행되는 프로세스를 분기합니다.["zsh", "-c", "cmd"]

관련 정보