Linux / コマンド / realpath - 絶対パスと実際のパスを確認

realpathは相対パスに含まれる .、..、重複スラッシュおよびシンボリックリンクを処理して正規化されたパスを出力するコマンドです。ファイルの実際の位置を確認したり、二つのパスがどの位置として解釈されるかを比較したり、基準ディレクトリに対する相対パスを作成する際に便利です。

パス構成要素が必ず存在する必要があるかどうかは-e、-E、-mによって異なります。また、パス計算の結果だけでファイルを安全に開いたと見なすことはできないため、セキュリティの検証には別途注意が必要です。

realpathコマンドとは?

realpathはファイル名やディレクトリパスを正規化して出力します。一般的な結果は絶対パスであり、不必要な/、.、..の構成要素やシンボリックリンクが処理されます。

realpath ./docs/../images/logo.webp

現在の作業ディレクトリが/home/user/projectであれば、次のような結果が得られる場合があります。

/home/user/project/images/logo.webp

正確な結果は、現在の作業ディレクトリ、実際のディレクトリ構造およびシンボリックリンクの構成によって異なります。

基本的な文法と使い方

realpath [オプション] ファイル ...

複数のパスを指定すると、それぞれの処理結果を一行ずつ出力します。

realpath .
realpath ../logs/app.log
realpath /var//log/./nginx/../syslog

現在の作業ディレクトリの物理的なパスだけが必要な場合は、pwd -Pの方がより直接的です。realpathは、現在の位置だけでなく、指定された複数のパスを処理できます。

パス存在条件の選択

本稿はGNU Coreutils版を対象にしています。古い版には -E がない場合があるため、使用前に realpath --help と realpath --version を確認してください。例の /srv/... などは自分の環境にあるパスに置き換えます。

GNU realpathでは、パスがどの範囲まで実際に存在する必要があるか、オプションで選択できます。

オプション 存在条件
-E, --canonicalize 最後の構成要素がなくても許可します。GNUのデフォルト動作ですが、移植性のために明示できます。
-e, --canonicalize-existing 最後の項目を含むすべてのパス構成要素が実際に存在する必要があります。
-m, --canonicalize-missing 中間の構成要素がなくてもディレクトリであると仮定して文字列を正規化します。

-eで存在するパスのみを許可する

realpath -e /etc/passwd
realpath --canonicalize-existing /srv/app/config.yml

構成要素の1つでも存在しなかったりアクセスできなければ失敗します。末尾にスラッシュを付けた場合は、対象がディレクトリである必要もあります。実際に存在する対象だけを後続の作業に渡したい場合に便利ですが、検査直後に対象が変わる状況までは防げません。

-Eで最後の名前がなくても処理する

realpath -E /srv/uploads/new-file.txt

上位のパスは確認できますが、最後のファイルがまだ作成されていない状況に使用できます。GNUではデフォルトの動作ですが、POSIX環境の違いを減らすためには意図をオプションで示す方が良いです。

-mで存在しない中間パスまで計算する

realpath -m /srv/not-created/../future/file.txt

-mは、ファイルシステムにない構成要素もディレクトリのように扱います。パス文字列を事前に計算する際に便利ですが、出力パスが実際に存在するか作成可能かまでは保証しません。

シンボリックリンクと -L、-P、-s

..とシンボリックリンクが共にあるパスは、処理順序によって異なる場所になることがあります。

オプション 動作
-P, --physical シンボリックリンクに出会った時点で解釈し、その後に..を処理します。GNUのデフォルトモードです。
-L, --logical パス文字列の..を論理的に処理した後、シンボリックリンクを解釈します。
-s, --strip, --no-symlinks シンボリックリンクをたどらずに、ドット要素と重複するスラッシュだけを整理します。

物理的パスを確認する

realpath -P /srv/current/../shared

/srv/currentが他の場所を指すリンクであれば、まずその対象を解釈した後に親パスを計算します。

シンボリックリンクを保持して文字列だけを整理する

realpath -s -m /srv/current/../shared

-sと-mを一緒に使用すると、実際のファイルシステムのリンクをたどらずにパス文字列自体を整理できます。実際の対象場所が必要なときは、この組み合わせを使用してはいけません。

相対パスを出力する

--relative-toで基準ディレクトリを指定する

処理したパスを特定のディレクトリに対する相対パスとして出力することができます。

realpath --relative-to=/srv/www /srv/www/assets/css/site.css

出力は次の通りです。

assets/css/site.css

--relative-baseでサブパスのみ相対化する

対象が基準ディレクトリの下にある場合にのみ相対パスとして出力し、外部にある場合は絶対パスを維持することができます。

realpath --relative-base=/srv/www /srv/www/index.html /var/log/syslog

最初のパスは相対パスになり、2番目のパスは基準外にあるため絶対パスとして出力されます。

readlink -fとrealpathの違い

比較項目 realpath readlink -f
主な目的 ファイル名の正規化と相対パス変換 シンボリックリンク対象の出力における拡張正規化機能
相対出力 --relative-toと--relative-baseのサポート 通常、絶対正規パスを出力
推奨使用 パス正規化にはGNUのドキュメントがrealpathを推奨 リンクに保存されている対象文字列を確認するのが基本目的
移植性 オプションと基本存在条件の実装の違いを確認する必要がある -fはすべてのUnix実装で同一であるとは限らない

シェルスクリプトでの活用方法

設定ファイルの実際のパスを記録する

次の内容を resolve-config.sh に保存し、bash resolve-config.sh ./config.ini のように実在する設定ファイルを第1引数に指定します。成功すると正規化したパス、失敗するとエラーと終了状態1が得られます。コマンド置換は出力末尾の改行を除去するため、名前の末尾に改行があるファイルにはこの代入方法を使わないでください。

config=$(realpath -e -- "$1") || {
  printf '%s\n' '設定ファイルのパスを確認できません.' >&2
  exit 1
}

printf '設定ファイル: %s\n' "$config"

-eを使用してすべての構成要素が存在するか確認しますが、その後の使用時までファイルがそのままという保証はありません。

複数のファイル名を安全に区切る

-z または --zero は、各結果の末尾に改行の代わりに NUL文字(値が0の区切り文字)を出力します。

realpath -z -- file1 "file with space"

ファイル名に改行が含まれる可能性がある自動化で有用であり、結果を受け取るプログラムも NUL 区切りの入力をサポートしている必要があります。

パスの検証に使用する際の注意点

正規化とアクセス許可は異なる

正規化されたパスが特定のディレクトリの下に見えるからといって、読み取りや書き込みの権限が自動的に許可されるわけではありません。所有権、権限、ACL(アクセス制御リスト)、およびセキュリティポリシーを別途確認する必要があります。

検査と使用の間に対象が変わることがある

realpathで確認した後にファイルを開く間にシンボリックリンクやディレクトリが変わると、別の対象を使用することになる場合があります。セキュリティ境界では単純な文字列比較だけに依存せず、OSが提供する安全なファイルの開き方と権限分離を使用してください。

接頭辞の文字列比較に注意する

/srv/www-safeも文字列上/srv/wwwで始まります。基準パスの含有を確認する場合はディレクトリ境界まで考慮する必要があり、パスの正規化だけでは安全なサンドボックスは作れません。

主なオプションまとめ

オプション 説明
-E, --canonicalize 最後の構成要素がなくてもパスを正規化します。
-e, --canonicalize-existing すべての構成要素が実際に存在する必要があります。
-m, --canonicalize-missing 存在しない構成要素もディレクトリのように扱います。
-L, --logical ..を論理的に処理した後にシンボリックリンクを解釈します。
-P, --physical シンボリックリンクをまず解釈する物理的モードであり、GNUのデフォルトです。
-s, --no-symlinks シンボリックリンクを解釈せずにパス文字列を整理します。
--relative-to=ディレクトリ 指定したディレクトリを基準に相対パスを出力します。
--relative-base=ディレクトリ 基準以下のパスのみ相対パスとして出力します。
-q, --quiet 指定したパスに関する診断メッセージを抑制します。
-z, --zero 結果をNUL文字で区切ります。

FAQ

realpathは存在しないファイルにも使用できますか?

GNUのデフォルト動作または-Eでは、最後の構成要素がなくても処理できます。中間の構成要素まで存在しない可能性がある場合は-m、すべての構成要素の存在を要求する場合は-eを使用します。

realpathは常にシンボリックリンクを解釈しますか?

基本的な物理モードではシンボリックリンクを解釈します。リンクをたどらずにパス文字列だけを整理したい場合は、-sまたは--no-symlinksを使用します。

pwd -Pとrealpath .の違いは何ですか?

どちらも現在の位置の物理的絶対パスを表示できます。pwd -Pは現在の作業ディレクトリに特化しており、realpathは任意の複数のパスと存在条件、相対パス出力オプションを提供します。

realpathの結果だけを確認すればパス探索攻撃を防げますか?

いいえ。確認とファイル使用の間にパスが変わる可能性があり、権限の問題も別です。信頼境界では、安全なファイルオープンAPI、権限分離、およびディレクトリ境界チェックを併用する必要があります。

参考資料