Bei zwei beliebigen absoluten Unix-Pfad-Spezifikationen , könnte man jede Spezifikation als die Verkettung eines längsten gemeinsamen Präfixes und eines spezifischen Suffixes zerlegen. Beispiel:
/abc/bcd/cdf -> /abc/bcd + cdf
/abc/bcd/chi/hij -> /abc/bcd + chi/hij
Gibt es ein Unix-Dienstprogramm (oder Dienstprogramme), um eine solche Zerlegung zu berechnen? (Ich habe „oder Dienstprogramme“ hinzugefügt, falls es separate Dienstprogramme zum Berechnen des längsten gemeinsamen Präfixes und zum Berechnen relativer Pfade gibt.)
(Mir ist klar, dass es nicht sehr schwierig wäre, solche Dienstprogramme zu programmieren, aber ich versuche, wann immer möglich, Werkzeugen, die mehr oder weniger Standard sind, Vorrang vor maßgeschneiderten zu geben.)
Ich schreibe „Pfadspezifikation“ statt „Pfad“, um Probleme wie das Vorhandensein (der Pfade) in einem bestimmten Dateisystem, Links usw. zu umgehen.
Akzeptierte Antwort:
Sie können dies in einer Shell-Schleife tun. Der folgende Code sollte mit allen Arten von seltsamen Pfaden mit zusätzlichen Schrägstrichen funktionieren; wenn alle Ihre Pfade die Form /foo/bar
haben , können Sie mit etwas Einfacherem davonkommen.
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
}
Bestimmen Sie alternativ das längste gemeinsame Präfix der beiden Zeichenfolgen und kürzen Sie es auf sein letztes /
Zeichen (außer wenn das gemeinsame Präfix nur aus Schrägstrichen besteht).