web-dev-qa-db-ja.com

スクリプト自体を含むディレクトリからシンボリックリンクを介してシェルスクリプトを実行する

私の望みは、ディレクトリを変更して実行しないことです。私はjarファイルを使用しており、それを実行する必要があります。そのため、私はそれを行うための非常に基本的なシェルスクリプトを作成しました。

#!/bin/sh
Java -jar TreeForm.jar

次に、TreeForm.shではなくTreeFormとして保存しました。次に、以下のようにシンボリックリンクを作成しました。

ln -s /opt/TreeForm/TreeForm /usr/bin/
chmod +x /opt/TreeForm/TreeForm

正常に作成されました。しかし、実行すると、Javaから以下のエラーが発生します。

エラー:jarfile TreeForm.jarにアクセスできません

したがって、シェルスクリプトは独自のディレクトリを実行しないか、そのディレクトリを調べないようですが、現在のディレクトリで動作します。 TreeForm.jarのフルパスを指定してスクリプトファイルを変更したくありません。だから私は尋ねたかったのですが、現在のパスを変更したり、PATH変数にパスを追加したりせずに、スクリプトファイルに関連するファイルを見つける方法はありますか?または、現在の変数ではなく、スクリプトのパスを持つ変数はありますか?

2
Eray Erdin

シェルは、指示されない限り、別のディレクトリに変更しません。スクリプトで別のディレクトリでコマンドを実行する場合は、スクリプトからcdを呼び出します。

スクリプトへのパスは"$0"として利用できます。スクリプトがシンボリックリンクの場合、それはシンボリックリンクへのパスです。シンボリックリンクの最終的なターゲットを取得する場合は、 realpath を呼び出します(ほとんどのuniceでは使用できますが、Linuxでは使用できます(両方GNUおよびBusyBox)、FreeBSDおよびSolaris 11、ただしOSXは除く)。

cd "$(dirname "$(realpath "$0")")"

realpathは、GNU coreutilsへの比較的最近の追加です。バージョンが古すぎる場合は、古いreadlink -fを使用できます。GNU以外のシステムでは、 realpathが存在しない場合はreadlinkが存在する可能性がありますが、通常は1レベルのシンボリックリンクのみを調べます。ほとんどのreadlinkの実装には-fオプションがありません完全な解決を行うために。

シェルスクリプトが存在するディレクタは、その$0パラメータから派生できます。たとえば、dirnameを使用して、スクリプト内でこれを行うことができます。

cd $(dirname "$0")

これは、jarファイルがスクリプトが置かれているのと同じディレクトリにあることを前提としています。

シンボリックリンクを介してスクリプトを参照する場合(さらに、スクリプトとjarファイルが同じディレクトリにあると仮定する場合)は、次のような複雑なスクリプトでこれを行うことができます。

  • $0のパス名を見つけます(デフォルトの$PATHルックアップを使用する場合は簡単です)。
  • readlinkなどのプログラムを使用して、シンボリックリンクを読み取ります。これはPOSIXではありませんが、多くのLinuxシステムに存在します。
  • readlinkがない場合は、他の回避策(lsの出力の読み取りを含む)で可能です。
  • ただし、cdからthatの場所へのリンクを読みます。

参考文献:

1
Thomas Dickey
  1. シンボリックリンクを削除する
  2. 実行:PATH=$PATH:/opt/TreeForm/、次にexport PATH

変更を永続的にするには、2番目のポイントから.bashrcファイル(ユーザーのホームディレクトリ内)にコマンドを追加します。 (すべてのユーザーに対して)グローバルにしたい場合は、/etc/bash.bashrcに追加します

0
KWubbufetowicz