web-dev-qa-db-ja.com

シンボリックリンクなしの相対パスから絶対パスへの変換

シンボリックリンクを含む可能性がある相対パスから絶対(および正規化)パスを取得するUnixコマンドはありますか?

66
Benjamin

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)ユーティリティも付属しています とほぼ同じです。

83
Mat

移植性のあるように、 PWD variable は、シェルによって現在のディレクトリの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##*/}

シンボリックリンクをたどるポータブルな方法はありません。ディレクトリへのパスがある場合、ほとんどのunices $(cd -- "$dir" && pwd -P 2>/dev/null || pwd)はシンボリックリンクを使用しないパスを提供します。これは、シンボリックリンクを追跡するシェルがpwd -P(「物理的」)。

一部のuniceは、ファイルへの「物理」パスを出力するユーティリティを提供しています。

  • 合理的に最近のLinuxシステム(GNU coreutilsまたはBusyBox))には readlink -f があり、FreeBSD≥8.3、NetBSD≥4.0、およびOpenBSDまでさかのぼります2.2。
  • FreeBSD≥4.3には realpath があります(一部のLinuxシステムにも存在し、BusyBoxにあります)。
  • Perlが利用可能な場合は、 Cwd module を使用できます。

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

pwdはあなたのニーズに合っていますか?現在のディレクトリの絶対パスを提供します。または、多分あなたが望むのは realpath() です。

5
xanpeng

alisterおよびrss67 in この記事 最も安定していて互換性があり、最も簡単な方法を紹介します。これまでより良い方法を見たことがありませんでした。

RELPATH=./../
cd $RELPATH
ABSPATH=`pwd`

元の場所に戻りたい場合は、

ORGPATH=`pwd`
RELPATH=./../
cd $RELPATH
ABSPATH=`pwd`
cd $ORGPATH

または

RELPATH=./../
cd $RELPATH
ABSPATH=`pwd`
cd -

これがお役に立てば幸いです。これは私にとって最大の解決策でした。

3
Eonil

他のすべての人の答えを尊重して、私は以下の関数がどこでも見つけた他の関数よりも非常に簡単でLinux/MAC OSX間で移植できることを発見しました。誰かを助けるかもしれません。

#!/usr/bin/bash
get_absolute_path(){
    file_path=`pwd $1`
    echo "$file_path/$1"
}
#to assign to a variable
absolute_path=$(get_absolute_path "file.txt")
echo $absolute_path
0
lauksas

ここでの他の回答は問題ありませんでしたが、私のニーズには不十分でした。どのマシンのスクリプトでも使用できるソリューションが必要でした。私の解決策は、必要な場所でスクリプトから呼び出すことができるシェルスクリプトを作成することでした。

#!/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番目の引数からのパスを開始点として使用して、最初の引数のパスを解決します。最初の引数のみが指定されている場合、スクリプトは現在の作業ディレクトリからの相対パスを解決します。

0
Sildoreth

さらに、$1(通常${PWD})の定義済みパスがいくつかある場合は、次のように機能します。

CWD="${1:-${PredefinedAbsolutePath}}"
if [ "${CWD}" != "${PredefinedAbsolutePath}}" ]; then
    case $1 in
        /*) echo "CWD=${CWD}"; ;;
        *) CWD=$(realpath $1); echo "CWD=${CWD}"; ;;
    esac
fi
0
Nikhil