Anda dapat melakukannya seperti:
cd /usr///.//share/../share//man/man1 || exit
IFS=/; set -f
printf %.1s/ ${PWD%/*}
printf %s\\n "${PWD##*/}"
/u/s/m/man1
dan inilah 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/
yang cukup dekat untuk melakukan semua hal yang sama fungsi tidak di bawah ini. itu tidak menyingkat dengan tildes atau memasukkan $PWD
ke kepala untuk non-slash terkemuka seperti fungsinya (dan pada kenyataannya, tidak pernah mencetak slash utama) tetapi itu bisa ditangani sesudahnya. itu memproses komponen jalur nol, dan titik tunggal, dan menyingkirkan ..
kasus.
diberi man
jalur yang sama seperti di cd
atas yang dicetak:
u/s/m/man1
itu juga akan mencetak satu atau dua titik utama tambahan untuk setiap komponen jalur yang dimulai dengan itu dan bukan hanya satu atau dua titik.
Anda bertanya tentang melakukan lebih dari satu karakter untuk path-komponen yang dimulai dengan a .
. untuk melakukannya saya pikir setiap komponen akan memerlukan perhatian individu, dan karena saya ingin tahu, saya mencoba tangan saya untuk membuat jalur kanonik tanpa direktori perubahan. setelah beberapa trial-and-error saya akhirnya memutuskan satu-satunya cara untuk melakukannya dengan benar adalah melakukannya dua kali - mundur dan maju:
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:--}"
}
sehingga tidak pernah mengubah direktori atau mencoba mengonfirmasi keberadaan komponen jalur apa pun, tetapi meremas /
pembatas berulang dan menjatuhkan /./
komponen titik tunggal sepenuhnya, dan memproses /../
komponen titik ganda secara tepat.
ketika $IFS
diatur ke beberapa karakter non-spasi , urutan dua atau lebih $IFS
karakter akan menghasilkan satu atau lebih bidang nol. jadi beberapa tebasan berurutan berhasil pada argumen bernilai nol. hal yang sama berlaku untuk $IFS
tokoh utama . dan ketika set -- $1
terbelah, jika hasilnya $1
nol maka dimulai dengan garis miring, ${1:+$PWD}
jika tidak, maka saya masukkan $PWD
. dengan kata lain, jika argumen pertama tidak dimulai dengan garis miring, itu akan $PWD
dipertanyakan. itu sedekat ini dengan validasi jalur .
jika tidak, for
loop pertama secara terbalik membalikkan urutan komponen path, seperti:
1 2 3
1 2 3
2 1 3
3 2 1
... saat melakukan itu mengabaikan komponen titik-tunggal atau nol, dan untuk ..
itu tidak ...
1 .. 3
1 .. 3
3
3
... pass kedua membalikkan efek ini, dan saat melakukannya ia memeras setiap komponen menjadi 2-titik + char , atau 1-titik + char , atau char .
jadi itu harus bekerja ke jalur kanonik terlepas dari keberadaannya.
saya menambahkan / mengurangi sedikit ke loop kedua. sekarang set
lebih jarang (hanya sekali untuk setiap [!./]*
komponen) , dan case
evaluasi pola hubung singkat sebagian besar waktu (berkat pola yang disebutkan di atas) , dan termasuk evaluasi kecocokan ekor-panggilan terhadap ~
. jika semua atau bagian terdepan (sebagaimana dibagi pada seluruh komponen) dari jalur kanonik akhirnya dapat cocok ~
, bit yang cocok akan dilepas dan literal ~
akan diganti. untuk melakukan ini, saya harus memelihara salinan lengkap dari path disamping yang disingkat juga (karena mencocokkan path yang disingkat dengan ~
mungkin tidak akan sangat membantu) , dan ini disimpan $3
. yang terakhirwhile
cabang loop hanya dijalankan jika ~
dicocokkan sebagai subset dari $3
.
jika Anda menjalankannya dengan set -x
jejak diaktifkan, Anda dapat melihatnya bekerja.
$ (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
. Titik sering sangat umum dalam direktori tertentu untuk menjadi petunjuk yang sangat kecil ke tempat Anda harus mencari.