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 $PWD
fü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 man
Pfad wie cd
oben 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 $IFS
ein Nicht-Leerzeichen festgelegt ist , führt eine Folge von zwei oder mehr $IFS
Zeichen zu einem oder mehreren Nullfeldern. Daher werden mehrere aufeinanderfolgende Schrägstriche zu Argumenten mit Nullwerten verarbeitet. Gleiches gilt für eine $IFS
Hauptfigur. und so, wenn geteilt wird set -- $1
, wenn das Ergebnis $1
null 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 $PWD
vorangestellt. Das ist so nah wie die Pfadvalidierung .
Andernfalls for
invertiert 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 set
s weniger oft (nur einmal für jede [!./]*
Komponente) und Kurzschlüsse case
Muster 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 Letztewhile
Der Schleifenzweig wird nur ausgeführt, wenn er ~
als Teilmenge von übereinstimmt $3
.
Wenn Sie es mit set -x
aktiviertem 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.