Bash スクリプトを書いています。現在の作業ディレクトリが常にスクリプトが配置されているディレクトリである必要があります。
デフォルトの動作では、スクリプト内の現在の作業ディレクトリは、スクリプトを実行するシェルのディレクトリになりますが、この動作は望ましくありません。
ベストアンサー1
要約
#!/bin/bash
cd "$(dirname "$0")"
長々とした説明
これはどのように機能し、エッジケースやコーナーケースにどのように対処するのでしょうか?
- 対話型シェルでスクリプトを起動するコマンドを入力します。
- その対話型シェルは、スクリプトを実行するよう
bash
指示する名前を呼び出します。bash
- 次に、スクリプトを指す bash 引数を使用して
bash
呼び出します。dirname
- 最後に、の出力を引数として を
bash
呼び出します。cd
dirname
スクリプト呼び出しコマンド | bash 口論 |
dirname 口論 |
cd 口論 |
---|---|---|---|
foo ($PATH で見つかりました/path/to/foo ) |
/path/to/foo |
/path/to/foo |
/path/to |
bash foo |
foo |
foo |
. |
/foo |
/foo |
/foo |
/ |
./foo |
./foo |
./foo |
. |
"/pa th/to/foo" |
/pa th/to/foo |
/pa th/to/foo |
/pa th/to |
"./pa th/to/foo" |
./pa th/to/foo |
./pa th/to/foo |
./pa th/to |
"../pa th/to/foo" |
../pa th/to/foo |
../pa th/to/foo |
../pa th/to |
"../../pa th/to/foo" |
../../pa th/to/foo |
../../pa th/to/foo |
../../pa th/to |
"pa th/to/foo" |
pa th/to/foo |
pa th/to/foo |
pa th/to |
--help/foo |
--help/foo * |
該当なし | 該当なし |
--help |
該当なし** | 該当なし | 該当なし |
シンボリックリンクについて
このcd
コマンドは、シンボリックリンクが関係している場合は、シンボリックリンクをたどります。シンボリックリンクは通常、たどられるために存在しているため、ほとんどの場合、シンボリックリンクをたどるのが正しい方法です。スクリプトをロードするときに、数マイクロ秒前に同じシンボリックリンクをたどっても問題がなかったのに、スクリプト内のコードがシンボリックリンクをたどると、なぜ問題になるのでしょうか。
ハイフンで始まるコマンド引数の場合
上記の表でハイフンで始まる引数の 2 つのケース (それぞれ * と ** でマークされている) について詳しく説明します。
* の引数がdirname
で始まる可能性があるのは-
、相対パスの場合のみです--help/foo
。スクリプトが というサブディレクトリにある場合--help
、スクリプトの実行は となりbash --help/foo
、bash はそのオプションを認識しないため、エラー メッセージが表示されて中止されます。スクリプトは実行されないため、 が何を実行するか--help/foo
は問題になりません。cd "$(dirname "$0")"
** スクリプトを呼び出すと、同じディレクトリに--help
入力しているときにシェルがコマンドを見つけられなくなることに注意してください--help
。または、現在のディレクトリが含まれている場合、スクリプトはまたは$PATH
として実行され、常に文字の前に何かが付きます。/path/to/--help
./--help
-
bash が で区切られたパラメータを持つコマンドライン引数を導入しない限り、 で区切られたパラメータを含み、bash によって受け入れられる引数を bash に=
渡すことは不可能に近いでしょう。-
/
dirname
引数を受け入れることができる場合--
(bash組み込み関数はcd
確実に受け入れます--
)、スクリプトスニペットを次のように変更できます。
cd -- "$(dirname -- "$0")"
-
bash をすり抜けることができる、で始まる議論を構築する方法がわかったら、ぜひコメントしてください。
ご注意
上記のスニペットは bash 以外でも機能します/bin/sh
。