GNU/Linux >> Znalost Linux >  >> Linux

Rozložení specifikací cesty na nejdelší společnou předponu + příponu?

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).

Související:Jak upravit výstup -f pomocí barev pouze pomocí Awk a zobrazit zbytek výstupu?
Linux
  1. Jak správně přidat cestu k cestě?

  2. Jak čistě přidat do $path?

  3. Unix Case Regex?

  1. CD do neznámého adresáře na známé cestě?

  2. Vytvoření nového adresáře v C

  3. Ignorujte malá a velká písmena v glob() na Linuxu

  1. Krátký úvod k jednotkám cest

  2. Převeďte výstup ls na csv

  3. Zkontrolujte, zda je adresář úložištěm git (aniž byste do něj museli cd)