zsh 的 cd 有个很吸引我的特性:比如你在 ~/data/foo/horrible/dir/names 目录下,需要切换到 ~/data/bar/horrible/dir/names,只需执行: % pwd~/data/foo/horrible/dir/names% cd foo bar% pwd~/data/bar/horrible/dir/names 我的工作环境是 AIX 5.3,有多
zsh 的 cd 有个很吸引我的特性:比如你在 ~/data/foo/horrible/dir/names 目录下,需要切换到 ~/data/bar/horrible/dir/names,只需执行:
% pwd ~/data/foo/horrible/dir/names % cd foo bar % pwd ~/data/bar/horrible/dir/names
我的工作环境是 AIX 5.3,有多套开发环境,经常需要做这样的切换。一开始上面只有最原始的 c shell,因为权限问题,费了很大劲编译出了 bash,zsh 到现在还编不出来,呵呵。所以就自己动手增强一下 cd 命令。增强的功能有:
- 诸如 zsh 路径替换的功能;
- 支持短名(自动模式匹配),比如要进入 workspace/shell/curl,就输入 cd w/s/c,效果等价于 cd *w*/*s*/*c*。如果有多个路径同时匹配,就将他们全部输出到屏幕;
- 简写支持 CDPATH。使用相对路径时,如果当前目录下没找到匹配的路径,就到 CDPATH 下逐一检查。
因为我默认在短命的两头都加上了 *,你可以修改 $i = "*"$i"*" 这一句,改成符合你自己习惯的匹配方式,比如 $i = $i"*",值匹配开头~
cd Bash SHELL 目录 模式cd () { if [ $# -eq 0 ]; then command cd return $(true) elif [ $# -eq 1 ]; then if { command cd "$1" 2>/dev/null; }; then return $(true) fi cd_path_pattern=`echo "$1" | awk -F/ -v OFS=/ '{ for (i = 1; i <= NF; i++) { if ($i != "" && $i != "." && $i != ".." && index($i, "*") == 0) { $i = "*"$i"*" } } print $0 }'` if [ -z "$cd_path_pattern" ]; then unset cd_path_pattern return $(false) fi set $cd_path_pattern if [ $# -eq 1 -a "$1" != "$cd_path_pattern" ]; then command cd "$1" unset cd_path_pattern return $(true) elif [ $# -gt 1 ]; then # ignore file cd_path_dir_cnt=`file $cd_path_pattern | sed -n '/: directory/{s///; p}' | wc -l` if [ $cd_path_dir_cnt -eq 1 ]; then command cd `file $cd_path_pattern | sed -n '/: directory/{s///; p}'` unset cd_path_pattern unset cd_path_dir_cnt return $(true) elif [ $cd_path_dir_cnt -gt 1 ]; then file $cd_path_pattern | sed -n '/: directory/{s///; p}' >&2 unset cd_path_pattern unset cd_path_dir_cnt return $(false) fi fi pattern_with_cd_path=$(echo "$CDPATH" | sed 's/:/\n/g' | awk -F: '$0 && !a[$0]++' | while read pp; do pp=`echo "$pp/$cd_path_pattern" | sed "s#/\+#/#g"` set $pp if [ $# -eq 1 -a "$1" != "$pp" ]; then echo "$1" >&1 break elif [ $# -gt 1 ]; then cd_path_dir_cnt=`file $pp | sed -n '/: directory/{s///; p}' | wc -l` if [ $cd_path_dir_cnt -eq 1 ]; then file $pp | sed -n '/: directory/{s///; p}' >&1 break; elif [ $cd_path_dir_cnt -gt 1 ]; then file $pp | sed -n '/: directory/{s///; p}' >&2 break fi fi done) if [ ! -z "$pattern_with_cd_path" ]; then command cd "$pattern_with_cd_path" fi unset pattern_with_cd_path unset cd_path_pattern else command cd `pwd | sed "s/$1/$2/g"` fi }