今天早上看到@程序员的那些事转的一条微博《使用命令行快速操控文件系统》,文中作者介绍了他提升工作效率的一个命令行小工具,可以快速切换工作目录,我觉得蛮有意思的,小小研究了下。在原工具的基础上,我在 Github fork了一个改进的版本 —— mark-directory,具体可以看文章最后。

工作原理

这个小工具的工作原理非常简单,相信大家扫过一遍原文就可以明白,它创建了一个隐藏目录(例如~/.marks),目录里面存放的文件都是常用目录的软链接。我们可以将这个软链接看作一个书签,通过访问这个书签我们可以方便地跳转到相应的目录。

具体实现

这个小工具也提供了相应的命令来管理这些软链接文件,当前支持的是jump, mark, unmark和marks。

以上4个操作命令的实现代码如下所示,非常简单:

export MARKPATH=$HOME/.marks
function jump { 
    cd -P "$MARKPATH/$1" 2>/dev/null || echo "No such mark: $1"
}
function mark { 
    mkdir -p "$MARKPATH"; ln -s "$(pwd)" "$MARKPATH/$1"
}
function unmark { 
    rm -i "$MARKPATH/$1"
}
function marks {
    ls -l "$MARKPATH" | sed 's/  / /g' | cut -d' ' -f9- | sed 's/ -/\t-/g' && echo
}

将这段代码放到~/.bashrc 文件中。接下来我们来尝试使用这个小工具。

首先,我们 cd 到一个常用的目录,使用 mark 为该目录创建一个书签,根据上面的代码,实际上是在~/.marks 目录下面创建了一个软链接文件:

[kodango@mac] ~ 
$ cd /usr/local/Cellar/

[kodango@mac] /usr/local/Cellar 
$ mark cellar

随后,使用 marks 命令来列出当前存在的书签:

[kodango@mac] /usr/local/Cellar 
$ marks

cellar	-> /usr/local/Cellar

我们跳转到其它目录,然后看看这个书签是否能正常工作,这时候我们要用到 jump 命令:

[kodango@mac] /usr/local/Cellar 
$ cd

[kodango@mac] ~ 
$ jump cellar

[kodango@mac] /usr/local/Cellar 

看似一切工作正常,如果你不想再要cellar 这个书签,可以通过 unmark 命令删除:

[kodango@mac] /usr/local/Cellar 
$ unmark cellar && marks
remove /Users/kodango/.marks/cellar? y

是不是很简单方便呢?

自动补全

懒人都会问,你这个能支持自动补全吗?当然可以,将以下补全代码添加到 ~/.bashrc 文件中:

_completemarks() {
  local curw=${COMP_WORDS[COMP_CWORD]}
  local wordlist=$(find $MARKPATH -type l -printf "%f\n")
  COMPREPLY=($(compgen -W '${wordlist[@]}' -- "$curw"))
  return 0
}

complete -F _completemarks jump unmark

当输入 jump 或者 unmark 命令后,按下 TAB 键:

[kodango@mac] /usr 
$ jump 
cellar  usr  

问题与改进

我 fork 了一个改进的版本(其实原版也没啥问题):

  • 增加一键式部署和卸载脚本;
  • 改进自动补全函数,仅补全第一个参数;
  • 改进 marks 函数的实现,兼容MAC OSX 与 GNU Linux 系统;
  • mark 命令默认将当前目录的名称作为书签名;
  • 命令错误输出重定向到标准错误,提示更加丰富;
  • 更加智能的 jump 命令,就像 cd 命令一样;

安装方法:

# git clone https://github.com/dangoakachan/mark-directory
# cd mark-directory
# sh install_markrc.sh
# source ~/.markrc

使用方法:

$ g /your/favorite/direcotry     # uh... just jump to the directory directly
$ s a-name-you-like              # save a mark with name 'a-name-you-like'
$ g                              # like `cd`, jump to your home
$ g -                            # like `cd -`, jump to last visited directory
$ g a-name-you-like              # jump to the marked directory based on the name  
$ g a-name                       # the same as above, the mark name will be expanded
$ p                              # list all predefined marks
$ d a-name-you-like              # delete the mark

更多信息请参考 mark-directory 项目的 README

更新历史

2013-09-05

感谢@breezeoverblow同学提醒,Mac OSX 系统默认是不存在~/.bash_profile 文件的,已经在部署脚本中修复该问题。[commit #08e3f855ca]