와일드카드를 사용한 결과 순서가 터미널이나 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.Peterv가 지적했습니다.), 셸은 대화형으로 실행되기 때문에 일반적으로 구성 파일을 읽습니다. 예를 들어 ~/.zshrc(셸이 zsh), 일부 설정은 와일드카드 완성 방법에 영향을 미칠 수 있습니다.

예를 들어:

내 쉘은 zsh다음과 같습니다. 내 쉘에는 하나가 있습니다.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(내 경우 데비안 ash)은 로케일을 존중하지 않으며 C 로케일처럼 정렬됩니다.

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

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

perls는 여러 인수를 전달할 때 system()암시적으로 쉘을 호출하지 않으므로 위의 프로세스는 프로세스를 분기하고 해당 프로세스에서 인수 /bin/zsh["zsh", "-c", "cmd"]실행합니다 .

관련 정보