このコマンドを実行すると、Gnu / Linuxは実際に何をしていますか?
cd; ls /Bin/g* &> /dev/null; echo $?
最終出力はゼロです。
答え1
g
その文字で始まる名前がディレクトリにあることを確認することが目的であれば、シェル/Bin
にはより良いアプローチがあります。bash
shopt -s nullglob
set -- /Bin/g*
if [ "$#" -ne 0 ]; then
printf 'There are %d names starting with "g" in /Bin\n' "$#"
echo 'These are those names:'
printf '\t%s\n' "$@"
else
echo 'No names in /Bin start with "g"'
fi
実行中のシステムにいると仮定するとbash
...
0
パターンと一致する名前があり、パターンと一致する名前がない場合、または一部のディレクトリ権限がそれを許可しない場合、コマンドセットはゼロ以外の/Bin/g*
値(おそらく2
ゼロではない可能性があります)を出力します。 ) を出力してリストを生成します。1
ls
最初に始めることはcd
興味深いものではなく、おそらく必要ではありません(このコマンドを削除すると影響を与える状況は非常に人為的です)。現在のディレクトリを任意の値に変更するか、設定されていない場合(または同等のデータベース)$HOME
で/etc/passwd
定義されたホームディレクトリに変更します。HOME
コマンドを実行する前に、ls
シェルは/Bin/g*
パターンを一致する名前のリストに展開します。ディレクトリリストを読み取る権限があり、/Bin
ディレクトリ/Bin
に文字で始まる名前があるg
場合は、その名前リストがの引数であるパターンを置き換えますls
。一致するものがない場合、または正しいアクセス権がない場合、/Bin
パターンはそのまま残ります。
実行すると、ls
シェル拡張によって提供された引数のリストを取得し、その名前を/Bin/g*
リストしようとします。これらの名前が存在し、あなたに何らかの名前をリストする権限があることを考慮すると、サブディレクトリ/Bin
文字で始まるg
コマンドはls
最終的に正常に終了し、終了ステータスを返します0
。名前がこの場合いいえ存在するか名前のいずれかがリストする権限を持たないサブディレクトリを参照すると、ゼロ以外の終了状態で失敗します(この場合はGNUから返されますls
)。2
これは、シェル&>/dev/null
から標準出力と標準エラーストリームにリダイレクトするリダイレクトです。実行すると、これはコマンドのすべての出力とすべてのエラーが削除されることを意味します(記録された特殊なデバイスファイルです。すべてのデータが削除されます)。入るとき)。リダイレクト演算子は標準ではなく、「標準出力にリダイレクトしてから、標準エラーを標準出力がある場所にリダイレクトします」と書く方が良いでしょう。技術的には、このステップはシェルがワイルドカードパターンを拡張する前にも発生します。bash
/dev/null
ls
/dev/null
&>
>/dev/null 2>&1
/dev/null
/Bin/g*
最後に、echo $?
最新の終了ステータスを出力します。これは終了ステータスls
(またはスキーマ拡張の失敗によって発生したエラーコード、または見つからないか、まったく実行され/Bin/g*
なかったために発生したエラーコードである可能性がある、以下を参照)です。ls
$PATH
これに影響する2つのシェルオプションがあります。
このオプションが現在のシェルセッションで設定されている場合、
nullglob
モード/Bin/g*
は次のようになります。完全に削除維持されるより。これはls
引数なしで実行され、リストが表示されることを意味します。現在のディレクトリ(ホームディレクトリにすることができますcd
)。現在のディレクトリを読み取る権限がある場合、これは成功します。ディレクトリの内容を読み取る権限がない場合は、ゼロ以外のls
終了ステータスが返されます(この場合はGNUls
が返されます)。1
シェルオプションが設定され、
failglob
パターンに一致する名前が/Bin/*
ない場合シェル文句を言い、no match: /Bin/g*
ゼロ以外の終了状態を取得します(おそらくまったく実行されません1
)。ls
エラーメッセージの生成はシェルで、シェルの標準エラーストリームは次のとおりです。いいえこのエラーメッセージは最終印刷の前に端末に印刷されます
/dev/null
(これはリダイレクトされた出力ストリームにすぎず、ls
この場合は実行されないことを覚えておいてください)。ls
echo $?
1
シェル変数は以下に影響します。
この変数は、シェルが引用符なしの値を拡張したときに適用されます
IFS
。これがecho $?
最後のステップ( )で行うことです。シェルが$?
正しい値で呼び出されるように拡張されると、最初にecho
文字を区切り文字として使用して値を単語に分割します。$IFS
デフォルトでは、$IFS
これはスペース、タブ、および改行です。IFS
文字列に設定すると(012
GNUを使用している場合は可能な値です)、シェルは値(の終了状態)を空の文字列に分割します(値が区切り文字として扱われるため)。引数なしで呼び出されると、出力として単一の改行文字が生成されます。$?
bash
ls
$?
ls
echo
このような不幸な状況を回避するには、次のものを使用できます
echo "$?"
(二重引用符を参照$?
)。
含まれていません:
PATH
ls
になければ何が起こり、起こらないのか、そしてこれがに$PATH
影響しないのはなぜですか?cd
echo
- 実際にコマンドを実行することに関連するすべて、
fork
+exec
など。 - エイリアスは、ツールのシェル機能またはを拡張またはオーバーライドします
cd
。ls
echo
- シェル以外の
bash
場所では何が起こりますか、その理由は何ですか? - 効果
set -f
。