şöyle yapabilirsiniz:
cd /usr///.//share/../share//man/man1 || exit
IFS=/; set -f
printf %.1s/ ${PWD%/*}
printf %s\\n "${PWD##*/}"
/u/s/m/man1
ve işte bir 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/
Bu, işlevin aşağıda yaptığı şeylerin hepsini yapmaya oldukça yakındır. tildes ile kısaltma yapmaz veya $PWD
fonksiyonun yaptığı gibi bir eğik çizgi için başa yerleştirmez (ve aslında, asla eğik çizgi yazdırmaz) ancak daha sonra ele alınabilir. null yol bileşenlerini ve tek noktaları işler ve ..
vakaları ayıklar .
yukarıdakiyle aynı man
yol verildiğinde cd
yazdırılır:
u/s/m/man1
bununla başlayan ve yalnızca bir veya iki nokta olmayan her yol bileşeni için bir veya iki ekstra ön nokta yazdırır.
a ile başlayan bir yol bileşeni için birden fazla karakter yapmayı istediniz .
. Bunu yapmak için her bileşenin yine de bireysel ilgi gerektireceğini düşündüm ve merak ettiğim için, değişiklik dizini olmadan kanonik bir yol üzerinde çalışmayı denedim. bazı deneme yanılma sonra nihayet doğru yapmanın tek yolu iki kez - geri ve ileri yapmak olduğuna karar verdi:
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:--}"
}
böylece hiçbir zaman dizini değiştirmez veya herhangi bir yol bileşeninin varlığını onaylamaya çalışmaz, ancak yinelenen /
sınırlayıcıları sıkar ve /./
tek noktalı bileşenleri tamamen bırakır ve /../
çift noktalı bileşenleri uygun şekilde işler .
zaman $IFS
bazı ayarlandığında boşluk olmayan karakterine, iki veya daha fazla bir sekans $IFS
karakterlerin bir veya daha fazla boş alanları ile sonuçlanacaktır. bu yüzden ardışık çoklu eğik çizgiler null değerli argümanlar için işe yarar. aynı şey önde gelen bir $IFS
karakter için de geçerlidir . ve böylece set -- $1
böler, eğer sonuç $1
null ise, o zaman bir eğik çizgi ile başladı, başka, ${1:+$PWD}
null değilse, o zaman eklerim $PWD
. başka bir deyişle, eğer ilk argüman eğik çizgi ile başlamazsa, başlayacaktır $PWD
. bu yol doğrulamaya geldiği kadar yakın .
aksi takdirde, ilk for
döngü, aşağıdaki gibi yol bileşenlerinin sırasını tekrar tekrar tersine çevirir:
1 2 3
1 2 3
2 1 3
3 2 1
... bunu yaparken herhangi bir tek noktalı veya boş bileşeni yok sayar ve ..
bunun için ...
1 .. 3
1 .. 3
3
3
... ikinci geçiş bu efekti tersine çevirir ve bunu yaparken her bileşeni 2 nokta + karakter veya 1 nokta + karakter veya karakter olarak sıkıştırır .
bu yüzden varoluşundan bağımsız olarak kanonik bir yol üzerinde çalışmalıdır.
i ikinci döngüye biraz ekledi / çıkardı. şimdi set
daha az sıklıkta (her [!./]*
bileşen için sadece bir kez ) ve kısa devre case
desen değerlendirmeleri çoğu zaman (daha önce bahsedilen desen sayesinde) ve karşı çağrı eşleştirme değerlendirmesi içerir ~
. nihayet kanonik yolun tamamı veya bir ön kısmı (bütün bileşenlere bölünmüş olarak) eşleşebilirse ~
, eşleşen bit çıkarılır ve değişmez bir yer ~
değiştirilir. Bunu yapmak için, kısaltılmış yanında yolun tam bir kopyasını korumak zorunda kaldı (çünkü kısaltılmış yolu ~
muhtemelen çok yararlı olmaz) , ve bu tutulur $3
. sonwhile
döngü dalı yalnızca ~
bir alt kümesi olarak eşleştirilirse çalıştırılır $3
.
set -x
izleme etkin olarak çalıştırırsanız çalışmasını izleyebilirsiniz.
$ (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
. Nokta, belirli bir dizinde genellikle aradığınız yere çok küçük bir ipucu olacak kadar yaygındır.