回答:
オプションを指定readlink
してユーティリティを使用でき-f
ます。
-f, --canonicalize
canonicalize by following every symlink in every component of the given name recursively; all but the last component must exist
GNU coreutilsとFreeBSDを使用するディストリビューションなど、一部のディストリビューションには、realpath(1)
基本的に呼び出しrealpath(3)
てほぼ同じことを実行するユーティリティも付属しています。
readlink
も付属していませんrealpath
。
brew install coreutils
apple.stackexchange.com/a/69332/23040、およびすべての標準Mac CLIツールを新しくインストールされたGNU同等物にリダイレクトするステップを実行したくない場合は、を呼び出しますgreadlink
。
移植性があるため、PWD
変数はシェルによって現在のディレクトリの1つの絶対位置に設定されます。そのパスのコンポーネントはシンボリックリンクである場合があります。
case $f in
/*) absolute=$f;;
*) absolute=$PWD/$f;;
esac
削除.
したい場合は..
、ファイルを含むディレクトリに移動して、$PWD
そこから入手してください:
if [ -d "$f" ]; then f=$f/.; fi
absolute=$(cd "$(dirname -- "$f")"; printf %s. "$PWD")
absolute=${absolute%?}
absolute=$absolute/${f##*/}
シンボリックリンクをたどるポータブルな方法はありません。ディレクトリへのパスがある場合、$(cd -- "$dir" && pwd -P 2>/dev/null || pwd)
シンボリックリンクを追跡するシェルは実装する傾向があるため、ほとんどの大学ではシンボリックリンクを使用しないパスを提供しますpwd -P
(「物理」の「P」)。
一部の大学は、ファイルへの「物理」パスを出力するユーティリティを提供します。
readlink -f
、FreeBSD≥8.3、NetBSD≥4.0、およびOpenBSD 2.2があります。realpath
(一部のLinuxシステムにも存在し、BusyBoxにあります)があります。perl -MCwd -e 'print Cwd::realpath($ARGV[0])' path/to/file
pwd
($(cd -- "$dir" && pwd -P 2>/dev/null | pwd)
)に何かをパイプするのですか?標準入力は気にしないようです。
||
であるpwd
あなたのニーズに合いますか?現在のディレクトリの絶対パスを提供します。または多分あなたが望むのはrealpath()です。
alister
そして、rss67
で、この記事で最も安定した互換性と最も簡単な方法をご紹介します。これよりも良い方法を見たことはありません。
RELPATH=./../
cd $RELPATH
ABSPATH=`pwd`
元の場所に戻りたい場合は、
ORGPATH=`pwd`
RELPATH=./../
cd $RELPATH
ABSPATH=`pwd`
cd $ORGPATH
または
RELPATH=./../
cd $RELPATH
ABSPATH=`pwd`
cd -
これが役に立てば幸いです。これは私にとって最大の解決策でした。
ABSPATH=$(cd -- "$RELPATH" && pwd)
。置換を囲む二重引用符(パスに空白文字とグロビング文字が含まれている場合に壊れないように)と--
(パスがで始まる場合)に注意してください-
。また、これはディレクトリに対してのみ機能し、要求されたシンボリックリンクを正規化しません。詳細については私の答えをご覧ください。
ここでの他の答えは結構でしたが、私のニーズには不十分でした。どのマシンのスクリプトでも使用できるソリューションが必要でした。私の解決策は、必要なスクリプトから呼び出すことができるシェルスクリプトを作成することでした。
#!/bin/sh
if [ $# -eq 0 ] || [ $# -gt 2 ]; then
printf 'Usage: respath path [working-directory]\n' >&2
exit 1
fi
cantGoUp=
path=$1
if [ $# -gt 1 ]; then
cd "$2"
fi
cwd=`pwd -P` #Use -P option to account for directories that are actually symlinks
#Handle non-relative paths, which don't need resolution
if echo "$path" | grep '^/' > /dev/null ; then
printf '%s\n' "$path"
exit 0
fi
#Resolve for each occurrence of ".." at the beginning of the given path.
#For performance, don't worry about ".." in the middle of the path.
while true
do
case "$path" in
..*)
if [ "$cwd" = '/' ]; then
printf 'Invalid relative path\n' >&2
exit 1
fi
if [ "$path" = '..' ]; then
path=
else
path=`echo "$path" | sed 's;^\.\./;;'`
fi
cwd=`dirname $cwd`
;;
*)
break
;;
esac
done
cwd=`echo "$cwd" | sed 's;/$;;'`
if [ -z "$path" ]; then
if [ -z "$cwd" ]; then
cwd='/'
fi
printf '%s\n' "$cwd"
else
printf '%s/%s\n' "$cwd" "$path"
fi
このソリューションは、移植性のためにBourne Shell用に作成されています。「respath.sh」という名前のスクリプトにこれがあります。
このスクリプトは次のように使用できます。
respath.sh '/path/to/file'
またはこのように
respath.sh '/relative/path/here' '/path/to/resolve/relative/to'
スクリプトは、2番目の引数からのパスを開始点として使用して、最初の引数のパスを解決します。最初の引数のみが指定されている場合、スクリプトは現在の作業ディレクトリからの相対パスを解決します。
pwd
組み込みおよびサポートしていません-P
(BourneシェルがPOSIXシェルが行うように取り扱い、その論理の$ PWDを実装していませんでした)。
cd -P --
1番目の引数にいくつかの..が含まれている場合は、おそらく同様に使用する必要があります。
case
チェックはする必要があります..|../*)
代わりに..*
。
dirname $cwd
変数aにパス名(a = "whatever")が格納されているとします
1.潜在的なスペースを含むパスの場合:
c=$(grep -o " " <<< $a | wc -l); if (( $c > "0" )); then a=$(sed 's/ /\\ /g' <<< $a); fi
2.実際の質問、つまりパスを絶対パスに変換する場合:readlinkはsymlinkコンテンツを取得できます。これは次のように使用できます。(注readlink -f
は完璧でしたが、少なくともMac OS X bashでは使用できません。-fはFORMATSを表します。)
if [[ $(readlink $a) == "" ]]; then a=$(cd $a; pwd); else a=$(cd $(readlink $a); pwd); fi
3.学習pwd -P
した内容man pwd
:-Pは「物理的な現在の作業ディレクトリを表示する(すべてのシンボリックリンクが解決される)」ため、
if (( $(grep -o " " <<< $a | wc -l) > "0" )); then a=$(sed 's/ /\\ /g' <<< $a); fi; a=$(cd $a; pwd -P)
動作します。
結論:1と2を組み合わせて両方の要件を満たしますが、スペースを含むパス名はより簡潔な3ですでに処理されています。
-f
スイッチは、Mac OS X(10.8.5以上のような)に存在しません。-f
スイッチがなければ、エラーコードを返すだけです。