¿Por qué el orden de los resultados de los comodines puede ser diferente cuando se usan desde la terminal o desde Perl?

¿Por qué el orden de los resultados de los comodines puede ser diferente cuando se usan desde la terminal o desde Perl?

Hay una carpeta con un montón de archivos y un script de Perl que los enumera usando ls con un comodín como:

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

Me di cuenta de que si ejecuto exactamente el mismo comando desde mi terminal bash, obtendré los mismos resultados pero en un orden diferente.

¿Por qué podría ser esto? ¿El comodín se maneja de manera diferente en ambos contextos?

Ejemplo:

mkdir dir
touch dir/a_0 dir/a1_0

salida terminal:

dir/a_0
dir/a1_0

salida de perl:

dir/a1_0
dir/a_0

Respuesta1

La función de Perl system("cmd")normalmente bifurca un proceso y, en el proceso hijo, ejecuta el shell del sistema (normalmente /bin/sh) con argumentos, ["sh", "-c", "cmd"]para shanalizar y ejecutar esa línea de comando del shell.

Como optimización, a veces puede funcionar sin una llamada de shell, si cmdno contiene metacaracteres de shell (como caracteres entre comillas o caracteres globales o cosas como ;, &&...) aparte del espacio y la tabulación, pero aquí tenemos meta de shell -caracteres ya que tenemos un *.

Entonces, eso ls -U -1 dir/*será interpretado por el shell del sistema.

Es el shell el que se expande dir/*a una lista de archivos coincidentes pasados ​​a ls, por lo que la forma en que se hace depende del shell.

En una terminal, normalmente ejecuta su shell de inicio de sesión, que generalmente no es /bin/sh. Tambien comoanotado por peterph), ese shell, dado que se ejecuta de forma interactiva, normalmente leerá archivos de configuración como ~/.zshrc(si el shell es zsh) donde algunas configuraciones pueden afectar la forma en que se realiza la globalización.

Por ejemplo:

Mi caparazón es zshy tengo un setopt dotgloben mi ~/.zshrc, entonces:

$ echo *
.a d é f

Sin leer el ~/.zshrc:

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

Notarás que eso zshrespeta la configuración regional al ordenar la lista.

$ sh -c 'echo *'
d f é

sh(que en mi caso es Debian ash) no respeta la configuración regional y ordena como si estuviera en la configuración regional C.

Si desea perlinterpretar system()la línea de comando con un shell en particular, puede escribirlo:

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

Cuando se pasa más de un argumento, perlnunca system()llama implícitamente a un shell, por lo que arriba, bifurca un proceso en el que se ejecuta /bin/zshcomo ["zsh", "-c", "cmd"]argumentos.

información relacionada