ディレクトリにCDを挿入した後、私が最初にしたことは "ls"を使用することでした。多くの人がそうすると思います。そのため、両方の操作を実行するために.bashrcに関数を定義することにしました。これが私が思いついたものです:
cs() {
if [[ ! "$1" ]] && [[ ! "$HOME" ]]
then
echo "I am completely lost and can't go home!"
exit 1
fi
cd "$1" && ls --group-directories-first -h --color=auto
}
これは、パラメータを渡さない場合を除くすべての場合に機能します。 $HOMEを設定するかどうかにかかわらず、何もせずに終了します。私は最初の行を分解し、次のような結果を得ました。
cs() {
if [[ ! "$1" ]]
then
if [[ ! "$HOME" ]]
then
echo "I am completely lost and can't go home!"
exit 1
else
cd && ls --group-directories-first -h --color=auto
fi
else
cd "$1" && ls --group-directories-first -h --color=auto
fi
}
このコードは期待どおりに正しく機能します。その間に非常に奇妙な動作をするバージョンがあります(残念ながら保存しましたが、2つのバージョン間の違いは非常に小さいです)。ここでパラメータとして「cs」を生成すると、ディレクトリの「ls」が出力されます。 .. しかし、ディレクトリは変更されません!コードは "cd"に引数だけを渡し、lsは現在のディレクトリで作業しているデフォルトの動作に戻るので(この欠落しているバージョンでも同じです)、 "ls"を同じコードブロックに含めることです。です。
私はここで何が起こっているのか理解したいと思います。さて、スクリプトを学び始めたのはとても簡単な作業だと思いましたが、本当に良い学習機会になったようです。私にはほとんど同じように見えるこれらの機能がなぜ異なる動作をするのでしょうか?
ベストアンサー1
cd
関数に提供された元の引数リストを使用して実行し、コマンドを実行するだけですls
。
cs () {
cd "$@" && ls --group-directories-first --human-readable --color=auto
}
引数なしで関数を呼び出すと、拡張は"$@"
まったく発生せず、cd
現在のユーザーのホームディレクトリが変更されるか、適切な方法で失敗します。それ以外の場合、拡張は引用された引数のリストになります(cd
しばしば複数の引数を使用できることに注意してください)。
コマンドの内部ロジックは、cd
引数を受け取らずに設定しない場合をすでに処理しているため、HOME
関数を含める必要はありません。
exit
通常、関数内でそれを使用しないことをお勧めします。これは現在のシェルが終了するためです。逆に、関数がゼロ以外の終了状態を返すには、return 1
次のようにします。
ディレクトリの変更が成功しなかったというあなたのコメントは次のとおりです。または(パイプラインの各部分がサブシェルで実行されている)などのサブシェルでcd
関数を実行すると、cd
これが発生する可能性があります。呼び出しが成功しました。現在のディレクトリ(cd /)
cat somefile | while ...; do cd ...; done
cd
はい変更されましたが、サブシェルのローカル環境が変更され、親シェルには表示されません。子シェルは親シェルの環境を変更できません。