外部コマンドを使用してrealpath
ファイルの絶対パスを取得できます。
realpath tmp/toto
返品
/home/john/tmp/toto
bash
組み込み関数を使用して同じ効果を得ることはできますか?
ベストアンサー1
シェルには、bash
相対パス名が与えられた場合に絶対パスを明示的に取得する組み込み方法はありません。
zsh
シェルでは、次のことができます。
pathname=../../home/kk/.zshenv
print -r -- $pathname:P
そして返します/home/kk/.zshenv
(可能であれば、同様の方法ですべてのシンボリックリンクも解決されることに注意してくださいrealpath()
)。
では、bash
ディレクトリではなくパス名を指定でき、親ディレクトリへの検索アクセス権があると仮定する場合は、次のようにします。
$ pathname=../../home/kk/.zshenv
$ ( OLDPWD=- CDPATH= cd -P -- "${pathname%/*}" && printf '%s/%s\n' "$PWD" "${pathname##*/}" )
/home/kk/.zshenv
つまり、ファイルが一時的に格納されている(サブシェル上の)ディレクトリは、その値とパス名のファイル名部分をcd
使用して絶対パス名を設定するために使用されます。部品を特別に取り扱うことは避けてください$PWD
。ディレクトリ自体のシンボリックリンクコンポーネントを解決する副作用があります。ただし、ファイル自体がシンボリックリンクである場合(s修飾子とは異なり)、解決されません。-P
cd
..
zsh
:P
私たちは代わりにを使用してこの問題をOLDPWD
解決し始めました(このトリックは機能しますが、他のすべての実装では機能しません)。-
cd -P -- -
chdir($OLDPWD)
chdir("-")
bash
sh
ディレクトリパスがより簡単です。
$ pathname=../../home/kk
$ ( OLDPWD=- CDPATH= cd -P -- "$pathname" && pwd )
/home/kk
便宜上、これは明らかにシェル関数に含めることができる。
myrealpath () (
if [[ -d $1 ]]; then
OLDPWD=- CDPATH= cd -P -- "$1" && pwd
else
OLDPWD=- CDPATH= cd -P -- "${1%/*}" && printf '%s/%s\n' "$PWD" "${1##*/}"
fi
)
(呼び出しシェルの作業ディレクトリが変更されないようにするために、関数全体がサブシェルで定義されています。)
この機能をテストしてみてください。
$ myrealpath ../../home/kk
/home/kk
$ myrealpath ../../home/kk/.zshenv
/home/kk/.zshenv
オペレーティングシステムによっては、パラメータなしで関数を使用すると、現在のディレクトリの絶対パスが返されるか、エラーが発生します。将来のリリースではエラーがPOSIXの要件になるため、bash
これはすべてのシステムのバグになる可能性があります。cd ''