
(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 -f
Linux(一部の簡略化された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
注:この関数はディレクトリ名に対してこのケースを処理しません。)