Por que a ordem dos resultados de caractere curinga pode ser diferente quando usada no terminal ou no perl?

2

Há uma pasta com vários arquivos e um script perl que os lista usando ls com um caractere curinga, como:

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

Percebi que, se eu executar exatamente o mesmo comando do meu terminal bash, obtenho os mesmos resultados, mas eles estão em uma ordem diferente.

Por que isso pode ser? O curinga é tratado de maneira diferente em ambos os contextos?

Exemplo:

mkdir dir
touch dir/a_0 dir/a1_0
Saída de terminal

:

dir/a_0
dir/a1_0

saída perl:

dir/a1_0
dir/a_0
    
por Luis 10.10.2013 / 10:36

1 resposta

6

A função system("cmd") de Perl geralmente bifurca um processo e, no processo filho, executa o shell do sistema (geralmente /bin/sh ) com argumentos, ["sh", "-c", "cmd"] , para ter sh parse e executar essa linha de comando do shell.

Como uma otimização, às vezes pode ficar sem uma chamada de shell, se cmd não contiver nenhum meta-caractere de shell (como caractere de citação ou caracteres globbing ou coisas como ; , && ...) diferente de espaço e tabulação, mas aqui temos metacaracteres do shell, pois temos um * .

Então, esse ls -U -1 dir/* será interpretado pelo shell do sistema.

É o shell que expande dir/* para uma lista de arquivos correspondentes passados para ls , então o modo como é feito depende do shell.

Em um terminal, você normalmente executa seu shell de login, que geralmente não é /bin/sh . Também (como anotado por peterph ), esse shell, uma vez que é executado interativamente, normalmente lerá arquivos de configuração como ~/.zshrc (se o shell for zsh ) onde algumas configurações podem afetar a forma como o globbing é feito. / p>

Por exemplo:

Meu shell é zsh e eu tenho um setopt dotglob no meu ~/.zshrc , então:

$ echo *
.a d é f

Sem ler o ~/.zshrc :

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

Você notará que zsh respeita a localidade ao classificar a lista.

$ sh -c 'echo *'
d f é

sh (que no meu caso é o Debian ash ) não honra a localidade e classifica como se estivesse na localidade C.

Se você quiser que perl do system() interprete a linha de comando com um determinado shell, você pode escrevê-lo:

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

Quando ultrapassado esse argumento, perl ' system() nunca chama implicitamente um shell, então, acima, ele bifurca um processo no qual ele executa /bin/zsh com ["zsh", "-c", "cmd"] como argumentos.

    
por 10.10.2013 / 12:43