複数のファイルと、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
Perlsystem("cmd")
機能は通常、プロセスを分岐し、サブプロセスでシステムのシェル(通常はシェル)を実行し、そのシェルを解析して実行するコマンドラインを/bin/sh
引数として使用します。["sh", "-c", "cmd"]
sh
最適化として、スペースやタブ以外のcmd
シェルメタ文字(引用符やワイルドカード文字など)が含まれていない場合は、シェル呼び出しは不要ですが、これには;
シェルメタ文字があります。&&
- 文字があるので*
。
したがって、これはls -U -1 dir/*
システムのシェルによって解釈されます。
シェルはdir/*
渡された一致するファイルのリストに展開されるため、ls
実行方法はシェルによって異なります。
端末では通常ログインシェルを実行しますが、通常はそうではありません/bin/sh
。Petervが指摘した。)、シェルは対話的に実行されるため、通常は構成ファイルを読み込みます。たとえば~/.zshrc
(シェルzsh
)、一部の設定はワイルドカードの完成方法に影響を与える可能性があります。
たとえば、
私のシェルはzsh
次のとおりです。私のシェルには1つあります。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
sは複数の引数を渡すときにsystem()
暗黙的にシェルを呼び出さないため、上記のプロセスはプロセスを分岐し、そのプロセスで引数/bin/zsh
として["zsh", "-c", "cmd"]
実行します。