Jsou-li dány jakékoli dvě absolutní unixové cesty specifikace lze každou specifikaci rozložit jako zřetězení nejdelší společné předpony a specifické přípony. Např.
/abc/bcd/cdf -> /abc/bcd + cdf
/abc/bcd/chi/hij -> /abc/bcd + chi/hij
Existuje unixový nástroj (nebo nástroje) pro výpočet takového rozkladu? (Přidal jsem „nebo nástroje“ pro případ, že existují samostatné nástroje pro výpočet nejdelší společné předpony a pro výpočet relativních cest.)
(Uvědomuji si, že by nebylo extrémně obtížné takové nástroje nakódovat, ale pokud je to možné, snažím se upřednostňovat nástroje, které jsou víceméně standardní před těmi na zakázku.)
Píšu „specifikace cesty“ spíše než „cesta“, abych se vyhnul problémům, jako je existence (cest) v daném souborovém systému, odkazy atd.
Přijatá odpověď:
Můžete to udělat ve smyčce. Níže uvedený kód by měl fungovat se všemi druhy podivných cest s extra lomítky; pokud jsou všechny vaše cesty ve tvaru /foo/bar
, můžete si vystačit s něčím jednodušším.
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
}
Případně určete nejdelší společnou předponu dvou řetězců a ořízněte ji na poslední /
znak (kromě případů, kdy se společná předpona skládá pouze z lomítek).