Sie können es tun wie:
cd /usr///.//share/../share//man/man1 || exit
IFS=/; set -f
printf %.1s/ ${PWD%/*}
printf %s\\n "${PWD##*/}"
/u/s/m/man1
und hier ist ein sed:
printf %s "$file" |
tr /\\n \\n/ | sed -et$ \
-e '\|^\.\.$|{x;s|\(.*\)\n.*$|\1|;x;}' \
-e 's|^\.\{0,2\}$||;\|.|H;$!d;x' \
-e$ -e '\|\(\.\{0,2\}.\)\(.*\)\(\n\)|!b' \
-e 's||\1\3\2\3|;P;s|\n||;D' |
tr /\\n \\n/
das kommt ziemlich nahe daran, all die gleichen Dinge zu tun, die die Funktion unten macht. Es wird nicht mit Tildes abgekürzt oder $PWDfür einen führenden Nicht-Schrägstrich in den Kopf eingefügt, wie dies bei der Funktion der Fall ist (und tatsächlich wird der führende Schrägstrich nie gedruckt), aber das könnte später behandelt werden. Es verarbeitet Nullpfadkomponenten und Einzelpunkte und beseitigt ..Fälle.
Bei gleichem manPfad wie cdoben wird Folgendes gedruckt:
u/s/m/man1
Außerdem werden ein oder zwei zusätzliche führende Punkte für jede Pfadkomponente gedruckt, die mit einer solchen beginnt und nicht nur aus einem oder zwei Punkten besteht.
Sie haben gefragt, ob Sie mehr als das eine Zeichen für eine Pfadkomponente tun möchten, beginnend mit a .. Um dies zu tun, dachte ich, dass jede Komponente sowieso individuelle Aufmerksamkeit benötigen würde, und weil ich neugierig war, versuchte ich mich daran, einen kanonischen Pfad ohne das Änderungsverzeichnis auszuarbeiten. Nach einigem Ausprobieren entschied ich schließlich, dass der einzige Weg, es richtig zu machen, darin bestand, es zweimal zu tun - vorwärts und rückwärts:
pathbytes(){
local IFS=/ o="$-" p
set -f${ZSH_VERSION+LFy}
set -- ${1:-$PWD}
for p in /${1:+$PWD} $*
do case $p in (.|"") ;;
(..) ${1+shift} ;;
(/) set -- ;;
(*) set -- $p $*; esac
done
for p in //$* ""
do case ${p:-/$3} in
([!./]*) ;;
(..*) set "..$@" ;;
(.*) set ".$@" ;;
(//*) ! set "" $1 $1 ;;
(~) ! p=\~ ;;
(~/*) p="~/$2";set $HOME
! while "${2+shift}" 2>&3
do p="~/${p#??*/}"
done 3>/dev/null;;
esac&& set "" "${p%"${p#$1?}"}/$2" "$p/$3"
done; printf %s\\n "${p:-$2}"
set +f "-${o:--}"
}
Damit wird niemals das Verzeichnis geändert oder versucht, die Existenz einer Pfadkomponente zu bestätigen, sondern es werden wiederholte /Trennzeichen gequetscht und /./Einzelpunktkomponenten vollständig gelöscht und /../Doppelpunktkomponenten entsprechend verarbeitet.
Wenn $IFSein Nicht-Leerzeichen festgelegt ist , führt eine Folge von zwei oder mehr $IFSZeichen zu einem oder mehreren Nullfeldern. Daher werden mehrere aufeinanderfolgende Schrägstriche zu Argumenten mit Nullwerten verarbeitet. Gleiches gilt für eine $IFSHauptfigur. und so, wenn geteilt wird set -- $1, wenn das Ergebnis $1null ist, dann begann es mit einem Schrägstrich, sonst, ${1:+$PWD}wenn es nicht null ist, dann füge ich ein $PWD. Mit anderen Worten, wenn das erste Argument nicht mit einem Schrägstrich beginnt, wird es $PWDvorangestellt. Das ist so nah wie die Pfadvalidierung .
Andernfalls forinvertiert die erste Schleife rekursiv die Reihenfolge der Pfadkomponenten wie:
1 2 3
1 2 3
2 1 3
3 2 1
... dabei werden Einzelpunkt- oder Nullkomponenten ignoriert, und ..das tut es auch ...
1 .. 3
1 .. 3
3
3
... der zweite Durchgang kehrt diesen Effekt um und drückt dabei jede Komponente entweder auf 2 Punkte + Zeichen oder 1 Punkt + Zeichen oder Zeichen .
es sollte also unabhängig von der Existenz zu einem kanonischen Weg führen.
Ich habe ein wenig zur zweiten Schleife addiert / subtrahiert. Jetzt sets weniger oft (nur einmal für jede [!./]*Komponente) und Kurzschlüsse caseMuster Auswertungen der meiste Zeit (dank das oben genannte Muster) und enthält eine Tail-Call - Match-Auswertung gegen ~. Wenn alle oder ein führender Teil (wie auf ganze Komponenten aufgeteilt) des endgültig kanonischen Pfades übereinstimmen können ~, wird das Übereinstimmungsbit entfernt und ein Literal ~ersetzt. Um dies zu tun, musste ich neben dem abgekürzten Pfad auch eine vollständige Kopie des Pfads pflegen (da es ~wahrscheinlich nicht sehr hilfreich wäre, den abgekürzten Pfad mit zu verknüpfen) , und dies wird beibehalten $3. das LetztewhileDer Schleifenzweig wird nur ausgeführt, wenn er ~als Teilmenge von übereinstimmt $3.
Wenn Sie es mit set -xaktiviertem Trace ausführen, können Sie beobachten, wie es funktioniert.
$ (set -x;pathbytes ..abc/def/123///././//.././../.xzy/mno)
+ pathbytes ..abc/def/123///././//.././../.xzy/mno
+ local IFS=/ o=xsmi p
+ set -f
+ set -- ..abc def 123 . . .. . .. .xzy mno
+ set --
+ set -- home
+ set -- mikeserv home
+ set -- ..abc mikeserv home
+ set -- def ..abc mikeserv home
+ set -- 123 def ..abc mikeserv home
+ shift
+ shift
+ set -- .xzy ..abc mikeserv home
+ set -- mno .xzy ..abc mikeserv home
+ set mno mno
+ set . mno mno
+ set .x/mno .xzy/mno
+ set .. .x/mno .xzy/mno
+ set ..a/.x/mno ..abc/.xzy/mno
+ set m/..a/.x/mno mikeserv/..abc/.xzy/mno
+ set h/m/..a/.x/mno home/mikeserv/..abc/.xzy/mno
+ p=~/h/m/..a/.x/mno
+ set home mikeserv
+ shift
+ p=~/m/..a/.x/mno
+ shift
+ p=~/..a/.x/mno
+
+ printf %s\n ~/..a/.x/mno
~/..a/.x/mno
+ set +f -xsmi
/f/b/.c/wizard_magic. Der Punkt ist in einem bestimmten Verzeichnis häufig so häufig, dass er nur einen sehr kleinen Hinweis darauf gibt, wo Sie suchen sollten.