Given any two absolute Unix path specs1, one could decompose each spec as the concatenation of a longest common prefix and a specific suffix.  E.g.,/abc/bcd/cdf     -> /abc/bcd + cdf/abc/bcd/chi/hij -> /abc/bcd + chi/hijIs there a Unix utility (or utilities) to compute such decomposition?  (I added or utilities in case there are separate utilities for computing the longest common prefix and for computing relative paths.)(I realize that it would not be extremely difficult to code such utilities, but I try to give priority to tools that are more or less standard over custom-made ones, whenever possible.)1I write path spec rather than path to sidestep issues like existence (of the paths) in a given filesystem, links, etc.
Decomposition of path specs into longest-common-prefix + suffix
path;utilities
You can do that in a shell loop. The code below should work with all kinds of strange paths with extra slashes; if all your paths are of the form /foo/bar, you can get away with something simpler.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}Alternatively, determine the longest common prefix of the two strings and trim it to its last / character (except when the common prefix consists solely of slashes).