関数の「cd」は、そうでない場合を除いて機能します。

関数の「cd」は、そうでない場合を除いて機能します。

ディレクトリに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 ...; donecdはい変更されましたが、サブシェルのローカル環境が変更され、親シェルには表示されません。子シェルは親シェルの環境を変更できません。

答え2

cs() {
    ...
    cd "$1" && ls --group-directories-first -h --color=auto
}

これは、パラメータを渡さない場合を除くすべての場合に機能します。

パラメータがないと$1設定されません(たとえば$2、、、$3...)。ただし、設定されていないパラメータを引用符で囲んで展開すると、"$1"NULL値を持つパラメータと同じように動作します。つまり、空の文字列に展開されます。これは、またlsはとls ""比較するなど、パラメータのないものとは異なりますunset foo; ls "$foo"

の場合cd、Bashの動作は、cd引数のない呼び出しは現在のディレクトリに移動し、空の文字列を引数$HOMEとしてcd使用する呼び出しは自動的に現在のディレクトリに移動することです。

(使用する場合はシェルによって異なります-P。引数が空の文字列の場合、デフォルトの関数呼び出しはエラーchdir()を提供する必要があり、Bashはを使用してそのエラーを公開するように見えますcd -P。と"無効なディレクトリ"エラー)chdir().cd ""cd -P ""

関数のすべてのパラメータをに渡すには、をcd使用しますcd "$@"。 1つの文字列を生成する別の二重引用符拡張とは異なり、位置引数全体が別の"$@"文字列として生成されます(または他のシェル「単語」のためにコマンドの他の引数が発生します)。したがって、引数がない場合はcd "$1"just に等しく、cd ""これはcd "$@"just に等しくなりますcd

$HOMEを設定するかどうかにかかわらず、何もせずに終了します。

なぜテストが機能しないのか理解できないので、$HOMEこれについては言及しません。

関連情報