Diberikan dua jalur Unix absolut spesifikasi , seseorang dapat menguraikan setiap spesifikasi sebagai rangkaian dari awalan umum terpanjang dan akhiran tertentu. Mis.,
/abc/bcd/cdf -> /abc/bcd + cdf
/abc/bcd/chi/hij -> /abc/bcd + chi/hij
Apakah ada utilitas Unix (atau utilitas) untuk menghitung dekomposisi seperti itu? (Saya menambahkan "atau utilitas" jika ada utilitas terpisah untuk menghitung awalan umum terpanjang dan untuk menghitung jalur relatif.)
(Saya menyadari bahwa tidak akan terlalu sulit untuk membuat kode utilitas seperti itu, tetapi saya mencoba untuk memprioritaskan alat yang kurang lebih standar daripada yang dibuat khusus, bila memungkinkan.)
Saya menulis "path spec" daripada "path" untuk menghindari masalah seperti keberadaan (path) dalam sistem file tertentu, tautan, dll.
Jawaban yang Diterima:
Anda dapat melakukannya dalam loop shell. Kode di bawah ini harus bekerja dengan semua jenis jalur aneh dengan garis miring ekstra; jika semua jalur Anda dalam bentuk /foo/bar
, Anda bisa lolos dengan sesuatu yang lebih sederhana.
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
}
Atau, tentukan awalan umum terpanjang dari dua string dan potong ke /
terakhirnya karakter (kecuali jika awalan umum hanya terdiri dari garis miring).