您可以这样做:
cd /usr///.//share/../share//man/man1 || exit
IFS=/; set -f
printf %.1s/ ${PWD%/*}
printf %s\\n "${PWD##*/}"
/u/s/m/man1
这是一个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/
这几乎可以完成以下功能要做的所有相同的事情。它不会像波浪线一样缩写,也不会$PWD
像函数一样插入到开头的斜杠(实际上,从不打印斜杠),但是可以在以后处理。它确实处理空路径分量和单点,并清除..
情况。
给出与上面相同的man
路径cd
:
u/s/m/man1
它还会为每个以此开头的路径分量打印一个或两个额外的前导点,而不仅仅是一个或两个点。
您问过,对于以a开头的路径组件,您需要做的不只是一个字符.
。为此,我认为每个组件无论如何都需要个人的关注,并且由于我很好奇,因此我尝试着制定出没有更改目录的规范路径。经过反复试验,我最终决定做对的唯一方法是做两次-来回移动:
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:--}"
}
因此,它永远不会更改目录或尝试确认任何路径组件的存在,但会压缩重复的/
定界符并/./
完全丢弃单点组件,并/../
适当地处理双点组件。
当$IFS
设置为某些非空白字符时,两个或多个$IFS
字符的序列将导致一个或多个空字段。因此,多个连续的斜杠可以计算出空值参数。主角也是如此$IFS
。因此,当set -- $1
拆分时,如果结果$1
为null,则以斜杠开头;否则,${1:+$PWD}
如果非null,则我插入$PWD
。换句话说,如果第一个参数不以斜杠开头,它将被$PWD
放在前面。这与路径验证差不多。
否则,第一个for
循环递归地反转路径组件的顺序,例如:
1 2 3
1 2 3
2 1 3
3 2 1
...这样做时它会忽略任何单点或null分量,并且..
确实如此...
1 .. 3
1 .. 3
3
3
...第二遍使该效果相反,同时这样做将每个组件压缩为2-dot + char或1-dot + char或char。
因此,无论存在与否,它都应该走一条规范的道路。
我增加/减去了第二个循环。现在,它set
的使用频率降低了(每个[!./]*
组件仅一次),并且case
大多数时候都使模式评估短路(由于上述模式),并且包括针对的尾声匹配评估~
。如果最终规范路径的全部或开头部分(按整个组件划分)都可以匹配~
,则将剥离匹配位,并~
替换文字。为了做到这一点,我还必须在缩写词的旁边维护路径的完整副本(因为将缩写词的路径匹配~
可能不会很有帮助),因此将其保留在中$3
。最后while
仅当~
匹配为的子集时才运行循环分支$3
。
如果在set -x
启用跟踪的情况下运行它,则可以观看它的运行情况。
$ (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
。该点在特定目录中通常很常见,以至于无法找到您应该去的地方。