Dati due percorsi Unix assoluti specifiche , è possibile scomporre ciascuna specifica come la concatenazione di un prefisso comune più lungo e di un suffisso specifico. Ad esempio,
/abc/bcd/cdf -> /abc/bcd + cdf
/abc/bcd/chi/hij -> /abc/bcd + chi/hij
Esiste un'utilità (o utilità) Unix per calcolare tale scomposizione? (Ho aggiunto "o utilità" nel caso ci siano utilità separate per il calcolo del prefisso comune più lungo e per il calcolo dei percorsi relativi.)
(Mi rendo conto che non sarebbe estremamente difficile codificare tali utilità, ma cerco di dare la priorità a strumenti più o meno standard rispetto a quelli personalizzati, quando possibile.)
Scrivo "specifica del percorso" anziché "percorso" per aggirare problemi come l'esistenza (dei percorsi) in un determinato filesystem, collegamenti, ecc.
Risposta accettata:
Puoi farlo in un ciclo di shell. Il codice seguente dovrebbe funzionare con tutti i tipi di percorsi strani con barre aggiuntive; se tutti i tuoi percorsi sono nella forma /foo/bar
, puoi farla franca con qualcosa di più semplice.
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
}
In alternativa, determina il prefisso comune più lungo delle due stringhe e ritaglialo fino all'ultimo /
carattere (tranne quando il prefisso comune è costituito esclusivamente da barre).