シンボリックリンクなしで相対パスを絶対パスに変換

シンボリックリンクなしで相対パスを絶対パスに変換

シンボリックリンクを含むことができる相対パスから絶対(および正規化された)パスを取得するUnixコマンドはありますか?

答え1

あなたはそれを使用することができます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コアツールそしてFreeBSDrealpath(1)、デフォルトでは呼び出しのみを実行するユーティリティも付属しています。realpath(3)そしてほぼ同じことをします。

答え2

ポータブルで、PWD変えるシェルによって現在のディレクトリの絶対位置に設定されます。このパスのすべてのコンポーネントはシンボリックリンクになります。

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##*/}

シンボリックリンクを追跡する移植可能な方法はありません。ディレクトリパスがある場合、ほとんどの unices は$(cd -- "$dir" && pwd -P 2>/dev/null || pwd)シンボリックリンクを使用せずにパスを提供します。シンボリックリンクに従うシェルはそうする傾向があるからですpwd -P(「P」は「物理的」を表す)。

一部のユニスは、ファイルの「物理的」パスを印刷するユーティリティを提供します。

  • 最新のLinuxシステム(GNU coreutilsまたはBusyBoxを含む)ではreadlink -f、FreeBSD ≥8.3、NetBSD ≥4.0、OpenBSD 2.2 の場合も同様です。
  • FreeBSD ≥4.3 例realpath(一部のLinuxシステムにも存在し、BusyBoxにあります)。
  • Perlが利用可能な場合は、次のものを使用できます。Cwd基準寸法

    perl -MCwd -e 'print Cwd::realpath($ARGV[0])' path/to/file
    

答え3

pwdあなたのニーズに適していますか?現在のディレクトリの絶対パスを提供します。またはあなたが望むものはおそらく実際のパス()

答え4

ここの他の答えは良いですが、私の要件には十分ではありません。すべてのコンピュータのスクリプトで利用可能なソリューションが必要です。私の解決策は、必要なスクリプトから呼び出すことができるシェルスクリプトを作成することでした。

#!/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 番目の引数のパスを始点として使用して、1 番目の引数のパスを解析します。最初の引数だけが指定された場合、スクリプトは現在の作業ディレクトリに基づいてパスを確認します。

関連情報