入れ子形式のシェルスクリプト(別のシェルスクリプトを内部的に呼び出すシェルスクリプト)を実行する場合、親のシェルスクリプトの呼び出し方によっては、子のシェルスクリプトを上手く呼び出せないことがあります。
たとえば、以下のような親子関係のある2つのシェルスクリプトが同じディレクトリ「/home/work」に格納されているとします。
#!/bin/sh ./child.sh
#!/bin/sh echo 'Hello World!'
カレントディレクトリが「/home/work」である場合に、「parent.sh」を実行した場合は、下記の通りになります。
$ pwd /home/work $ ./parent.sh Hello World!
しかしながら、これをカレントディレクトリが「/home/work」以外の場合に実行すると、「parent.sh」から「child.sh」が正しく呼ばれません。
たとえば、カレントディレクトリが「/home」の場合に、「parent.sh」を下記のように実行すると、結果は下記のようになります。
$ pwd /home $ ./work/parent.sh ./work/parent.sh: ./child.sh: not found
確かに、カレントディレクトリが「/home」のため、そこからの相対パスである「./child.sh」=「/home/child.sh」は見つからずエラーになるのは当然といえば当然ですが、シェルスクリプトを実行する際のカレントディレクトリを制限するのは、シェルスクリプトを実行する上で、何かと不便です。
このページでは、この問題を解決する方法について説明します。
上記の問題を解決するには、実行されているシェルスクリプトを知る「$0」なる特別の引数と、「dirname」を利用します。
これらの動きを知るために、「/home/work」に以下のようなシェルスクリプトを作って保存してみます。
#!/bin/sh echo $0 echo `dirname $0`
このシェルスクリプトを同じディレクトリ「/home/work」から実行したときの結果は以下の通りです。
$ pwd /home/work $ ./test.sh ./test.sh .
また、このシェルスクリプトを「/home」から実行したときの結果は以下の通りです。
$ pwd /home $ ./work/test.sh ./work/test.sh ./work
更に、このシェルスクリプトを「/」から実行したときの結果は以下の通りです。
$ pwd / $ ./home/work/test.sh ./home/work/test.sh ./home/work $ /home/work/test.sh /home/work/test.sh /home/work
このように、「$0」にはシェルスクリプトを実行する際に入力されたコマンドそのものを返し、「dirname $0」は「そのディレクトリへのパス」(相対パス/絶対パスを問わない)を返します。
説明が長くなりましたが、一番最初の「parent.sh」および「child.sh」の例において、これらが同じディレクトリにあれば、「parent.sh」の中で取得する「dirname $0」は「child.sh」のあるディレクトリと同一になります。
「parent.sh」を以下のように変更してみてください。
#!/bin/sh binary_path=`dirname $0` ${binary_path}/child.sh
このシェルスクリプト「parent.sh」を相対パス/絶対パスのどれで呼び出しても、且つカレントディレクトリが何処にあろうと、「child.sh」が正しく呼び出されます。
尚、子のシェルスクリプトの中で「dirname $0」を呼び出すと、親のシェルスクリプトの中での「dirname $0」の値と同じものが取得できます。
つまり、子のシェルスクリプトが同一のディレクトリ内にある孫のシェルスクリプトを呼ぶ際にも、以下のようにすれば正しく呼び出すことが可能です。
#!/bin/sh binary_path=`dirname $0` ${binary_path}/grandchild.sh
・「/home」からの「parent.sh」の実行の件で、parent.shの実行方法の記述が誤っていたのを修正。
ご指摘頂いた方、深く感謝です!
・頂いたメッセージは管理者のチェックの後、公開されます。
・メッセージの公開を希望されない場合には、「このメッセージを非公開にする」にチェックを入れてください。
・管理者が不適切と判断したメッセージは公開しませんので、予めご了承ください。
まさにこれだ 2 (100%) |
表示できるメッセージはありません。