任意の2つの絶対Unixパスspecs 、各仕様を最長の共通プレフィックスと特定のサフィックスの連結として分解できます。例:
/abc/bcd/cdf -> /abc/bcd + cdf
/abc/bcd/chi/hij -> /abc/bcd + chi/hij
そのような分解を計算するためのUnixユーティリティ(または複数のユーティリティ)はありますか? (最長の共通プレフィックスを計算するためのユーティリティと相対パスを計算するためのユーティリティが別々にある場合に備えて、「またはユーティリティ」を追加しました。)
(このようなユーティリティをコーディングすることはそれほど難しいことではないことを理解していますが、可能な限り、カスタムメイドのツールよりも多かれ少なかれ標準的なツールを優先するようにしています。)
特定のファイルシステムやリンクなどに(パスが)存在するなどの問題を回避するために、「パス」ではなく「パス仕様」を記述します。
承認された回答:
シェルループでそれを行うことができます。以下のコードは、余分なスラッシュを含むあらゆる種類の奇妙なパスで機能するはずです。すべてのパスが/foo/bar
の形式の場合 、もっと簡単なことで逃げることができます。
split_common_prefix () {
path1=$1
path2=$2
common_prefix=
## Handle initial // specially
case $path1 in
//[!/]*) case $path2 in
//[!/]*) common_prefix=/ path1=${path1#/} path2=${path2#/};;
*) return;;
esac;;
/*) case $path2 in
/*) :;;
*) return;;
esac;;
*) case $path2 in /*) return;; esac;;
esac
## Normalize multiple slashes
trailing_slash1= trailing_slash2=
case $path1 in */) trailing_slash1=/;; esac
case $path2 in */) trailing_slash2=/;; esac
path1=$(printf %s/ "$path1" | tr -s / /)
path2=$(printf %s/ "$path2" | tr -s / /)
if [ -z "$trailing_slash1" ]; then path1=${path1%/}; fi
if [ -z "$trailing_slash2" ]; then path2=${path2%/}; fi
## Handle the complete prefix case (faster, necessary for equality and
## for some cases with trailing slashes)
case $path1 in
"$path2")
common_prefix=$path1; path1= path2=
return;;
"$path2"/*)
common_prefix=$path2; path1=${path1#$common_prefix} path2=
return;;
esac
case $path2 in
"$path1"/*)
common_prefix=$path1; path1= path2=${path2#$common_prefix}
return;;
esac
## Handle the generic case
while prefix1=${path1%%/*} prefix2=${path2%%/*}
[ "$prefix1" = "$prefix2" ]
do
common_prefix=$common_prefix$prefix1/
path1=${path1#$prefix1/} path2=${path2#$prefix1/}
done
}
または、2つの文字列の最長の共通プレフィックスを決定し、最後の/
にトリミングします。 文字(共通プレフィックスがスラッシュのみで構成されている場合を除く)。