シェルスクリプトで「cd」が機能しないのはなぜですか?


43

ディレクトリ変更するスクリプトを書きたいだけです。

ファイルに以下のコマンドを入れます /home/alex/pathABC

#!/bin/sh
cd /home/alex/Documents/A/B/C
echo HelloWorld

やっchmod +x pathABC

ターミナルでは/home/alex、でを実行します./pathABCが、出力はHelloWorldそのままで、現在のディレクトリは変更されません。

それで何が悪いのでしょうか?


回答:


74

他の人が説明したように、ディレクトリは、スクリプトの呼び出し元のターミナルプロセスではなく、スクリプトの子プロセスで変更されます。子プロセスが終了すると、元の場所に残っているターミナルに戻ります。

いくつかの選択肢:

1.シンボリックリンク

簡単にアクセスしたい長いパスへのシンボリックリンクを家に置きます

$ ln -s /home/alex/Documents/A/B/C ~/pathABC

次に、ディレクトリにアクセスします。

$ cd ~/pathABC

2.エイリアス

〜/ .bashrcにエイリアスを置きます:

alias pathABC="cd /home/alex/Documents/A/B/C"

ここから)

3.機能

ディレクトリを変更する関数を作成します。関数は端末のプロセスで実行され、その後ディレクトリを変更できます。

ここから)

4.子として実行しないでください

スクリプトを実行する代わりにソースします。ソーシング(.またはsourceで実行)を実行すると、スクリプトは独自のサブシェルで実行されるのではなく、同じシェルで実行されます。

$ . ./pathABC

ここここから)

5. cd-able vars

cdable_varsオプションを設定~/.bashrcし、ディレクトリに環境変数を作成します。

shopt -s cdable_vars
export pathABC="/home/alex/Documents/A/B/C"

その後、使用することができます cd pathABC

ここから)


15
今、私はの使用法を理解していますsource!私は、なぜ私はいつも疑問に思ったsource .bashrcし、ないbash .bashrc
hytromo

オプション3はうまく機能しました。スクリプトの冒頭で関数go_to_wherever(){cd my / directory}を定義しました。そのディレクトリで操作を実行する前に呼び出します。
i2097i

> 5. cd-able vars-そうではありませんcd $pathABCか?
loxaxs

7

ターミナルでスクリプトを実行すると、子プロセスが実行されます。この子プログラムでは、スクリプトは指定されたディレクトリに変更されます。しかし、親プロセス、つまりスクリプトを実行する場所では、まだ古いパスにあります。または単に言うことができます:

The scope of cd command is only for child process not parent


2
これに加えて、@ alexを使用して、探している効果を達成し、ソースプロセスで親プロセス内でスクリプトを実行します:. pathABCまたはsource pathABC
zwets 14年

4

あなたは思考エラーを犯しています。現在のシェルが同じディレクトリにある間、スクリプトは新しいディレクトリに移動しました。

新しいディレクトリに別のスクリプトを作成し、ディレクトリを変更した後、スクリプトから実行することで、それを確認できます。

#!/bin/sh
cd /home/alex/Documents/A/B/C && ./another_script.sh # (if it is executable)

2番目のスクリプトは、新しいディレクトリから実行されます。

HelloWorld 

スクリプトの単なる出力です。


3
HelloWorldのは、標準出力に出力の親シェルに「返却」されていません
モグ

pwd状況にまったく新しいスクリプトを追加するのではなく、新しいディレクトリで実行するだけの場合は、より明確になる可能性があります。
wjandrea

0

Hello Worldは単なるトレースステートメントであるため、これを試してみましょう。

以下cd.shを含むbashスクリプトファイルを作成します。

#!/bin/bash
echo "/home/mike/Documents/A/B/C"
  • この.sh拡張子は、bashスクリプトのファイル名に拡張子を付けるという古い規則です。それは純粋に化粧品であり、通常は不要です。ただし、この場合、コアcdコマンドと区別することが重要です。

次を使用して、bashスクリプトファイルを実行可能としてマークします。

chmod a+x cd.sh

ファイルを実行します:

$ cd $(./cd.sh)
bash: cd: /home/alex/Documents/A/B/C: No such file or directory
  • cd 私たちは皆知っています。
  • $(...) 括弧内のコマンドを実行し、出力を返します。
  • cd.shパスにあった場合、それがどこにあるかを指定する必要はありません。./コマンドが現在のディレクトリにあることを指定するために接頭辞を付けます。
  • スクリプトechoからの出力は、cd.shを介して親に送り返され$(...)ます。親(シェルプロンプト)はこの出力を使用して、Linux cdコマンドに渡します。

他の人が言及したように、子プロセスは親のディレクトリを変更できません。これは、プロセスが終了した後、子が親にどこに行くべきかを伝える1つの方法です。


@wjandreaそれはあなたが電話でコーディングするために得るものです!ちょうど家に着いた、私はそれを修正します。ありがとう。ええと、それは正常に動作します。多分それは14.04私が約1時間前に読んだあなたのバージョンですか?
WinEunuuchs2Unix

さて、あなたはスクリプトを完全に変更しました。以前は、1つのコマンドcd /home/mike/Documents/A/B/Cでした。出力を生成しませんでした。これでecho "/home/mike/Documents/A/B/C"、出力が生成されます。
-wjandrea

@wjandrea確かに、スクリプトの呼び出し方法も完全に変更しました。単純な./cd.shものの代わりに今ではありますcd $(./cd.sh)が、親の現在のディレクトリを変更する子の目標を達成します。はい、それは型破りなものですが、人々が面白いと思うことを願うのは、それを行う別の方法です。
WinEunuuchs2Unix
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.