如何使使用 $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根本拒絕顯示任何內容,儘管它會計算符號連結的總大小)。

延伸閱讀:

相關內容