友好的交互式Bash

我是一名fish用户,生命中最痛苦的时刻就是被迫使用一台只有(TENEX)C Shell、Bash、KornShell、Z Shell的电脑而没有安装软件的权限。万幸的是,简单配置过后的Bash就变得可以使用了。

补全

Bash的默认补全功能有两个问题:

  1. 匹配文件时大小写敏感;
  2. 有多个候选时补全完全不起作用。

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"ReadlineShift-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

复制以下链接,并粘贴到你的Mastodon、MisskeyGoToSocial等应用的搜索栏中,即可搜到对应本文的嘟文。对嘟文进行的点赞、转发、评论,都会出现在本文底部。快去试试吧!

链接:https://emptystack.top/note/friendly-interactive-bash