zshでスクリプトの絶対パスを取得するUnixポータブル方法は何ですか?

zshでスクリプトの絶対パスを取得するUnixポータブル方法は何ですか?

(zsh)スクリプトが絶対パスを決定する移植可能な1つの方法は何ですか?

Linuxでは、次のようなものを使用します。

mypath=$(readlink -f $0)

...しかし、携帯することはできません。 (readlink例えば、ダーウィンはこのシンボルを認識しておらず、-fそれに対応するシンボルもありませんreadlink)。

移植可能な方法がありますか?


1つまり、Unix オペレーティングシステムファミリ全体に移植可能です。

答え1

zshでは、次のことができます。

mypath=${0:a}

または、スクリプトがあるディレクトリをインポートします。

mydir=${0:a:h}

バラより履歴拡張修飾子のZshドキュメント情報文書がインストールされている場合は、man zshexpnローカルで表示されます。info -f zsh -n Modifiers

答え2

の場合はzsh次のようになります。

mypath=$0:A

または

mypath=$0:P

最新バージョンでは(参照手動どう違うのかを学びましょう。)

他のシェルの場合realpath()readlink()標準機能(後者はシステムコール)ですが、標準コマンドではありませんが、一部のシステムにはrealpath異なるreadlink動作と機能セットがあるか、またはその両方があります。

通常、移植性のために次のものを使用できますperl

abs_path() {
  perl -MCwd -le '
    for (@ARGV) {
      if ($p = Cwd::abs_path $_) {
        print $p;
      } else {
        warn "abs_path: $_: $!\n";
        $ret = 1;
      }
    }
    exit $ret' "$@"
}

readlink -fファイルのディレクトリ名が存在しない限り、文句を言わないという点でrealpath()(GNU)よりもGNUのように動作します。readlink -e

答え3

私は数年間それを使ってきました:

# The absolute, canonical ( no ".." ) path to this script
canonical=$(cd -P -- "$(dirname -- "$0")" && printf '%s\n' "$(pwd -P)/$(basename -- "$0")")

答え4

絶対パス、つまりルートディレクトリのパスを意味すると仮定します。

case $0 in
  /*) mypath=$0;;
  *) mypath=$PWD/$0;;
esac

ところで、これはすべてのBourneスタイルのシェルで動作します。

すべてのシンボリックリンクが解決されたパスを意味する場合、話は異なります。readlink -fLinux(一部の簡略化されたBusyBoxシステムを除く)、FreeBSD、NetBSD、OpenBSD、およびCygwinでは機能しますが、OS / X、AIX、HP / UX、またはSolarisでは機能しません。ある場合は、readlinkループから呼び出すことができます。

realpath () {
  [ -e "$1" ] || return
  case $1 in
    /*) :;;
    *) set "$PWD/$1";;
  esac
  while [ -L "$1" ]; do
    set "${1%/*}" "$(readlink "$1")"
    case $2 in
      /*) set "$2";;
      *) if [ -z "$1" ]; then set "/$2"; else set "$(cd "$1" && pwd -P)/$2"; fi;;
    esac
  done
  case $1 in
    */.|*/..) set "$(cd "$1" && pwd -P)";;
    */./*|*/../*) set "$(cd "${1%/*}" && pwd -P)/${1##*/}"
  esac
  realpath=$1
}

それ以外の場合はreadlink近似を使用できますが、ls -nこれはlsファイル名から印刷できない文字を区切らない場合にのみ機能します。

poor_mans_readlink () {
  if [ -L "$1" ]; then
    set -- "$1" "$(LC_ALL=C command ls -n -- "$2"; echo z)"
    set -- "${2%??}"
    set -- "${2#*"$1 -> "}"
  fi
  printf '%s\n' "$1"
}

(追加のz場合は、リンク先が改行文字で終わる場合です。そうしないと、コマンドのオーバーライドは使い果たされます。realpath注:この関数はディレクトリ名に対してこのケースを処理しません。)

関連情報