答え1
realpath
私の頭では、これらのユーティリティのどれも仕様でこの機能を参照しているかどうかわかりません。
私が知っているすべてはテストディレクトリエントリの場合パス名は既存のディレクトリエントリで解決されます。1+x。
Peepでの実装ダッシュ(git.kernel.org)、それを使用lstat64/stat64。
これはディレクトリに十分です(テスト-Dパス名)到着CDその中に入り、解決されたパス名を返します。パスワード。
~のためCD、CDパス設定されていないか空白でなければならず、²オペランドはハイフンマイナス記号ではありません。「-」.³
([ -d "$1" ] && [ '-' != "$1" ] && CDPATH= cd -P -- "$1" && pwd -P)
例:ディレクトリの絶対パス、フルパス、実際のパス名を返します。ディレクトリで解決されていない場合はnullを返します。
パス名からハイフンマイナス記号( "-")を除外するのに問題がある場合、代替策はオペランドを "./-"に設定することです。
1参照テスト²参照CDステップ5の手順、参照。cd "-"オペランド
読んでみるとすでに知っています。ディレクトリ名そして基本名、そしておそらくどのようにシンボリックリンクが壊れているか存在しないことを確認してください。 Unix & Linuxそうでない場合は、その回答の文脈を確認して興味があるかどうかを確認してください。」テスト区別などの使い方テスト -d パス名1. 終了ステータス
答え2
質問を投稿した後、次の解決策を思い出しました。
#!/bin/sh
realpath() (
file=
path=$1
[ -d "$path" ] || {
file=/$(basename -- "$path")
path=$(dirname -- "$path")
}
{
path=$(cd -- "$path" && pwd)$file
} || exit $?
printf %s\\n "/${path#"${path%%[!/]*}"}"
)
警告:どうやらこれまでテストできませんでした!常にフィードバックを求めてください。もしご覧になった方は、コメントを残してください。
また、他の人も以前に同じアイデアを持っていて、特に極端なケースと広範なテストの後でよりよく解決したと確信しています。ご存知の方はリンクを投稿してください。
上記のシェル機能はrealpath
GNU coreutilsを置き換えますrealpath -s --
。https://www.gnu.org/software/coreutils/manual/html_node/realpath-inplication.html。これはシンボリックリンクが解決されなかったことを意味します。 (相対パス解決にのみ興味がある場合でも、これは必要ありません。)
-
#!/bin/sh
ShebangをPOSIXシェルとして使用します。
-
realpath() (
realpath() (...)
代わりにサブシェルで関数を実行しても、realpath() {...}
存在する可能性のあるfile
変数は上書きされませんpath
。 (POSIXシェルはローカル変数をサポートしていません。) -
file= path=$1
変数を定義します。最初に、引数によって提供されるパスが既存の
$1
ディレクトリであると仮定します。 (パスの最後のコンポーネントが削除しようとしているパスの反対側で.
ある場合もあるため、これは重要です。)..
-
[ -d "$path" ] || { file=/$(basename -- "$path") path=$(dirname -- "$path") }
関数引数が以前に想定したように既存のディレクトリへのパスではない場合は、
$path
Quote fromを調整する必要がありますman realpath
。解決された絶対ファイル名を印刷します。最後のコンポーネントを除いて、すべて存在する必要があります。
$file
したがって、(「最後のコンポーネント」)が実際に既存のファイルであるか、存在しないファイルまたはフォルダであるかは重要ではありません。$path
今すぐ削除し、最終的に再添付します。 -
{ path=$(cd -- "$path" && pwd)$file
ここで「トリック」が発生します。相対パスを解決するには、そのパス
cd
を解析してpwd
最終ディレクトリを印刷するために使用します。この新しいパスは$path
。2.6.3 コマンドの置換サブシェルで実行します。$file
最後に添付されます。 -
} || exit $?
{...}
この行は、前の行の変数割り当てを囲むコードブロックの理由です。ユーザーが間違ったパスを提供している場合(たとえば、最後のコンポーネントのみが存在しない場合)、cd
(コマンドオーバーライド内で)失敗し、stderrにエラーメッセージを印刷する必要があります(たとえば、「...」とCDできません。 ")。エラーコード> 0で終了します。これはコマンド置換サブシェルのエラーコードでもあります。このエラーコードにアクセスするには、$?
変数の割り当てがラップされます{...}
。したがって、{...}
ブロックが失敗した場合、関数は終了し、ゼロ以外の同じエラーコードを伝播します。 -
printf %s\\n "/${path#"${path%%[!/]*}"}"
//
または存在しない/a
などの極端なケースのため、結果はまたはa
です。だから//
//a
2.6.2 パラメータ拡張$path
最終出力に単一のスラッシュを追加する前に、すべての先行スラッシュを削除するために使用されます。
私が実行したいくつかのテストは次のとおりです。
for path in / // /// . .. "$HOME/." "$HOME/.." "*" --help /tmp /notexisting
do
if [ "$(realpath "$path")" != "$(/usr/bin/realpath -s -- "$path")" ]
then
printf %s\\n "$path"
fi
done