友好的交互式Bash
我是一名fish用户,生命中最痛苦的时刻就是被迫使用一台只有(TENEX)C Shell、Bash、KornShell、Z Shell的电脑而没有安装软件的权限。万幸的是,简单配置过后的Bash就变得可以使用了。
补全
Bash的默认补全功能有两个问题:
- 匹配文件时大小写敏感;
- 有多个候选时补全完全不起作用。
Bash的编辑功能是由Readline库实现的。在Readline的配置文件.inputrc中加入下面几行可以解决上述问题。
set completion-ignore-case On
set show-all-if-ambiguous On
set menu-complete-display-prefix On
TAB: menu-complete
"\e[Z": menu-complete-backward
set colored-stats On
配置中"\e[Z"是Readline的Shift-Tab键。至于每个选项的具体解释,可以用man readline
查看手册,或者搜索在线手册。总之这段配置的效果是:补全时无视大小写、Tab键与Shift-Tab键正反向循环候选列表。另外对候选文件开启高亮,区分不同文件类型。
fish在补全文件时是模糊匹配的,这一点不知道如何在Bash里实现。
某条命令的历史
如果我想重复某条命令的历史,在fish中只要输入那条命令然后一直按上箭头键就可以了。在原味Bash里,则要使用Ctrl-r开启反向搜索、输入命令、重复按下Ctrl-r组合键。万幸的是,Readline仍然可以拯救我们:
"\e[A": history-search-backward
"\e[B": history-search-forward
其中"\e[A"与"\e[B"分别代表上下箭头。这下输入export
再按上箭头,就只会显示以export
开头的历史了。
更省按键的移动
如果我直接往终端里输入文件路径,那我100%是要切换到那里。这一点,fish天生就懂,而Bash在执行shopt -s autocd
后也可以懂。
仅仅省掉cd
还不够:在返回多个上级目录时,重复输入../../..
仍然让我沮丧。既然.
是当前目录,..
是上一级,那么输入...
应该自动展开为../..
,以此类推。在fish中可以给句号键绑定一个能修改当前行的函数,Bash也可以——只不过要直接操作表示当前行和位置的变量。
expand-dots() {
if [[ $READLINE_LINE = *.. ]]; then
READLINE_LINE="$READLINE_LINE/.."
READLINE_POINT=$((READLINE_POINT + 3))
else
READLINE_LINE="$READLINE_LINE."
READLINE_POINT=$((READLINE_POINT + 1))
fi
}
bind -x '".": expand-dots'
到这里为止,在Bash里四处移动对我来说已经足够方便了。如果还想要更省按键的移动,可以用z——我是不喜欢source别人写的shell script。
其他功能
除去shopt -s autocd
,我的.bashrc里还有如下内容:
shopt -s checkjobs globstar
set -o noclobber
- checkjobs:在退出时如果仍有后台作业,Bash会让你再斟酌下要不要退出。
- globstar:**将会匹配所有文件、任意层级的子目录。
- noclobber:使用>重定向到已有文件时会报错。如果真要清空已有文件,使用|>替代>。