$0 を使用するスクリプトを $PATH 上にあるときに動作させるにはどうすればよいですか?

$0 を使用するスクリプトを $PATH 上にあるときに動作させるにはどうすればよいですか?

ソフト リンクを作成したスクリプト (~/.../gremlin) があります。

ln -s ~/[...]/gremlin ~/sc/gremlin

~/sc/gremlinは にあります$PATH
スクリプトを直接呼び出すと機能します。
リンクを介して呼び出すと機能しません。
を使用しているdirname $0ため、何も得られません。

スクリプトを変更せず、ソフト リンクの代わりに別のスクリプトを作成せずに、この設定を機能させる方法はありますか?

$0 は次のように使用されます:

case `uname` in
  CYGWIN*)
    CP=$( echo `dirname $0`/../lib/*.jar . | sed 's/ /;/g')
    ;;
  *)
    CP=$( echo `dirname $0`/../lib/*.jar . | sed 's/ /:/g')
esac

答え1

の使用がdirname $0問題かどうかは、どうやって使用されています。詳細がわからないため、回答できません。

(a) の使用にdirname $0問題があり、(b) スクリプトを変更できない場合は、ソフト リンクを~/sc/gremlinスクリプトに置き換えることが解決策になります。

#!/bin/sh
exec ~/../gremlin "$@"

この方法では、~/../gremlin正しい で実行されます$0

を使用すると、execスクリプトを実行しているプロセスが、~/../gremlinを実行しているプロセスを置き換えることになります~/sc/gremlin。これは、両方のプロセスが~/../gremlin完了するまで保持するよりも効率的です。

答え2

スクリプト内からではなく、~/...からディレクトリを取得する場合は、次のようにします。$0~/sc

スクリプトの場合zsh:

#! /bin/zsh -
dir=$0:A:h

readlinkそれ以外の場合、 GNU のコマンドのように動作するコマンドがある場合(一部のシステムrealpathでは代わりに使用できるコマンドがあります) :

#! /bin/sh -
dir=$(dirname -- "$(readlink -f -- "$0")")

readlink -fそして$0:Aあなたに正統なファイルのパス。これは、すべてのパス コンポーネント内のすべてのシンボリック リンクを解決した後の絶対パスです。

その後:

set -- "$dir"/../lib/*.jar .
case $(uname) in
  CYGWIN*) IFS=';';;
  *)       IFS=:;;
esac
CP="$*"

または:

case $(uname) in
  CYGWIN*) sep=';';;
  *)       sep=:;;
esac
CP=$(printf "%s$sep" "$dir"/../lib/*.jar).

答え3

@john1024 が指摘したように、OP の質問のタイプミスが質問のポイントである可能性があります。

ln -s ~/.../gremlin ~/sc/gremlin

いくつかのアプリケーションはトリプルドットを尊重しますが、Unixファイルシステムはそうではありません。シェル~は(チルダ)を展開しますが、lnは展開しません。

    ln -s ~/../gremlin ~/sc/gremlin

は、パス名を期待どおりに展開します。リンクがすでに存在する場合は、 オプションを使用して上書きできます-f。ただし、ターゲットが実際のファイルの場合、オプションはシンボリック リンクでファイルを暗黙的に上書きします。少なくとも、すでに何かが存在することを通知する オプション-fを使用することをお勧めします。-i

リンクを検証したい場合(リンクがファイルを指していることを証明したい場合)、-L次のオプションlsが便利です。

ls -lL ~/sc/gremlin

ファイルでない場合は、ls(実装に応じて)lタイプ(リストの最初の文字)として が表示され、パーミッション ビットとして疑問符が表示されるか、実際のファイルを指していないことを示すその他の表示が表示されます(OSX は、この場合、シンボリック リンクのサイズを合計に含めますが、何も表示しません)。

参考文献:

関連情報