goto,一个用于快速切换目录的脚本

在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上验证。

goto,一个用于快速切换目录的脚本》上有1条评论

  1. Pingback引用通告: goto的bash版本 | 在路上

发表评论

电子邮件地址不会被公开。 必填项已用*标注