親シェルの作業ディレクトリをプログラムで変更することは可能ですか?


8

普段行くディレクトリに切り替えられるように、コードを書きたいのですが。このプログラムがmycdであり/a/very/long/path/name、私が行きたいディレクトリであるとします。

したがって、のmycd 2代わりに単純に入力できcd /a/very/long/path/nameます。ここで私はmycd知っている2と思い/a/very/long/path/nameますそれを指します。またあるかもしれませんmycd 1mycd 3、...など

問題はmycd、シェルスクリプトとして記述し、入力. mycd 2して必要なことを行う必要があることです。それ以外の場合、スクリプトは子スクリプトで実行されるだけで、実際に関心のある親シェルについては何も変更されません。

私の質問は:

  • 使用せずにそれを行うことができsourceますか?ので、. mycd前提としては、mycdシェルスクリプトでなければならない、これはまた、私は望んでいないことをいくつかの機能を紹介することがあります。

  • 他のプログラミング言語で実装できますか?

回答:


23

コマンドを現在のシェルで実行できるようmycdに関数を作成cdします。〜/ .bashrcファイルに保存します。

function mycd {
    if (( $# == 0 )); then
        echo "usage: $FUNCNAME [1|2|3|...]"
        return
    fi
    case $1 in
        1) cd /tmp ;;
        2) cd /a/very/long/path/name ;;
        3) cd /some/where/else ;;
        *) echo "unknown parameter" ;;
    esac
}

ありがとう、関数の使用については考えていません。これですべてが可能になります。これで、好きなプログラムにmycd渡すことができます$@
Javran、2014

"$@"空白を含む引数が正しく処理されるように、引用符で囲んでください。
グレン・ジャックマン2014

9

シェルの現在のディレクトリを別のプロセスから変更することはできません。現在のディレクトリを変更できるのは、プロセス自体だけです。これは、環境変数やファイル記述子などの他の特性にも当てはまります。

chdirシステムコールを介してptraceシステムコールを実行させることにより、別のプロセスの現在のディレクトリに影響を与えることが実際に可能です。これにより、デバッガーが機能します。ただし、プロセスが実際の現在のディレクトリと一致する必要があるいくつかの内部データ構造を維持している場合、プログラムはクラッシュする可能性があります。シェルの場合、このアプローチは機能する機会がありません。

シェル自体によってコードが実行されるように準備する必要があります。続行する通常の方法は、それをシェル関数にしてに保存すること~/.bashrcです。配布したいコードなどが原因でこれが不可能な場合は、関数定義を含むシェルソースファイルを記述し、対話型シェルに.コマンドを使用してファイルを読み取らせるように指示します。


1
実際にそれを「機能させる」機会はありますが、それは重要で、エラーが発生しやすく、すべてのコストで回避する必要があります。実際に「可能」であることを示すために、親がBashである次のシェルスクリプトを考えてみますws=$1; gdb -p $(ps h -o ppid -p $$) -ex "call chdir(\"$wd\")" -ex "call set_working_directory(\"$wd\")" -ex detach -ex q -batch。として実行しbraindead-cd-parent /ます。あなたはそれが表示されますpwdリターン/とそうにls振る舞うなど、。ただし、プロンプト(PS1)は変更されない、人の目が傷つくなどです。可能な場合でも、これを行わないでください。
Lekensteyn 14

1
@Lekensteynそれはptrace私が言及する方法です。現在のディレクトリをあまり気にしないプログラムでうまく機能します。シェルでは、多くの事柄(PWD変数、プロンプトなど)が誤ったものになり、シェルがクラッシュしたり、その他の動作をすることがあります。
Gilles 'SO-悪をやめる'

5

ご指摘のとおり、シェルスクリプトは常にサブシェルで実行され、親シェルに影響を与えることはできません。

ただし、次のことができます...

  • エイリアスを使用:
    alias mycd2='cd /a/very/long/path/name'
  • スクリプト1に有効なシェルコマンドを出力させる...

    #!/bin/bash
    if [ "x$1" = "x2" ]
    then
        echo "cd /a/very/long/path/name"
    fi

    ...そしてその出力を実行します: $(mycd 2)

1:例の条件ではcaseなく、ステートメントを使用することをお勧めしますif


5
エイリアスは通過可能です。スクリプトは、彼がすでに抱えている問題と同じです。この質問シェル機能を叫びます。
Ricky Beam
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.