在shell下经常在不同的目录之间切换的话,希望有一个更好用的cd或pushd/popd命令。以前曾尝试过autojump, asdf 等工具,发现这些工具有些“重”了,它们背后通过ruby或python记录你每次cd的路径,统计出每个路径的频率,算出一个权重,根据权重优先来匹配跳转。我希望有一个更轻的(不用依赖ruby或python),不用那么“聪明”的,能够记录最近的路径并可以方便跳转过去的工具。
我的需求是列出之前切换过的10个目录,用序号记录,按时间排序,最近一次切换的目录排在第一位,效果如下:
$ dirs
1 /data/server/tomcat
2 /System/Library/Frameworks/JavaVM.framework/Versions/jdk1.8
3 /data/work/opensources/openjdk
4 /tmp/a b
5 /data/work/opensources/apache
6 /tmp
7 /Users/hongjiang
8 /Applications
9 /data/downloads
10 /data/tools
当我想要切换到某个目录时,只需要命令后边跟序号就可以,如下:
$ goto 2
$ pwd
/System/Library/Frameworks/JavaVM.framework/Versions/jdk1.8
$ goto 9
$ pwd
/data/downloads
这个效果可以通过几个函数来实现,首先是要把cd命令alias为pushd,这样每次切换目录都会压栈:
pushd() {
if [ $# -eq 0 ]; then
DIR="${HOME}"
else
DIR="$1"
fi
builtin pushd "${DIR}" > /dev/null
}
alias cd='pushd'
然后对内置的dirs命令进行包装:
dirs() {
tmphash="/tmp/.dirs"
builtin dirs -plv |
awk -F'\t' '{
if (a[$2]=="") a[$2]=$1;
if (length(a)==10) exit
}END{for(i in a) print a[i],i}' |
sort -nk1 | cut -d' ' -f2- > $tmphash
nl $tmphash
}
这样在每次执行dirs函数时,会通过内置的dirs命令过滤最近10次切换过的目录并保持在”/tmp/.dirs”文件里。最后实现goto函数:
goto() {
tmphash="/tmp/.dirs"
if [ ! -f $tmphash ]; then
echo "no record"
return 1
fi
if [ $# -eq 0 ]; then
return 1
fi
dest=`awk -v n=$1 'NR==n&&1' $tmphash`
if [[ $dest == "~" ]]; then
dest=${HOME}
elif [[ $dest == "~/"* ]]; then
dest="${HOME}/${dest:2}"
elif [[ $dest == "~"* ]]; then
dest=`eval "echo $dest"`
fi
pushd $dest
}
将上面几个函数放入.zshrc里,source一下或重启shell即可,只在zsh上测试过,还未在bash上验证。