我们来玩玩bash定制化界面:
ash (Bourne-again Shell) 是一个来自 GNU Project的命令行解释器/编程语言。它的名字是向它的前身——很早以前的 Bourne shell 致敬。Bash 可以运行在大部分类 UNIX 操作系统中,包括 GNU/Linux。
调用
Bash调用方式的不同会导致Bash运行方式的不同。下面是在不同模式下运行的Bash的描述。
登录外壳
如果Bash由在tty中的登录
, SSH 守护进程, 或者其它类似的方式而派生出来, 它就被称为登录外壳(shell)。你可以使用命令行选项-l
或者 --login
来使用这个种模式。
交互式外壳
如果Bash在启动的时候既没有使用 -c
选项也没有使用非选项参数,那我们就认为它是一个交互式外壳,同时Bash的标准输出和标准错误被链接到终端上。
符合 POSIX
通过在Bash启动时使用 --posix
命令行参数或者在启动后执行 ‘set -o posix
’ 来使Bash在增强的POSIX标准下运行。
传统模式
如果以命令名sh
来调用Bash, Bash会尽可能地模仿历史版本的sh
的启动过程,包括 POSIX 兼容性。
在传统模式下登陆运行的shell来源于/etc/profile,然后是~/.profile。
配置
通过如下配置文件进行配置:
/etc/profile
~/.bash_profile
~/.bash_login
~/.profile
/etc/bash.bashrc
(非标准: 只对部分发行版有效,Arch包含在这部分中)~/.bashrc
~/.bash_logout
常用的配置文件:
/etc/profile
被所有兼容Bourne shell的shell在登录时引用。它在登录时建立了环境并且加载了应用程序特定(/etc/profile.d/*.sh
)的设置。~/.profile
: 此文件在启动一个交互式的登录shell时被Bash所读入和引用。~/.bashrc
此文件在启动一个交互式的非登录shell时被Bash所读入和引用。比如当你从桌面环境中打开一个虚拟控制台时。这个文件在用户自定义自己的shell环境时特别有用。
配置文件在启动时的引用顺序
这些文件在不同的情形下被Bash所引用。
如果交互式+登录shell →
/etc/profile
然后按以下顺序读取~/.bash_profile
,~/.bash_login
, and~/.profile
Bash会在退出时引用{ic|~/.bash_logout}}。
如果交互式+非登录shell →
/etc/bash.bashrc
然后~/.bashrc
如果交互式+传统模式 →
/etc/profile
然后~/.profile
注意: 传统模式指以sh
来调用
外壳和环境变量
Bash的行为和通过它来运行的程序会被许多的环境变量所影响。环境变量被用于储存有用的值比如命令搜索路径,或者使用哪个浏览器。当一个新的shell或者脚本被执行时,这个shell会继承它的父shell的变量, 因此这个shell会以内部的shell变量启动。
这些Bash中的shell变量可以被导出以变成环境变量:
VARIABLE=content export VARIABLE
或者:
export VARIABLE=content
环境变量依照惯例放置在~/.profile
或者/etc/profile
,这样所有兼容Bourne shell的shell都可以使用。
参阅Environment variables以获得更加全面的信息。
命令行
Bash的命令行由一个叫做Readline的分离库来管理。Readline提供了很多Bash命令行交互的快捷键,比如说,光标单词间向前向后移动,删除单词等等。管理输入历史也是Readline的职责。最后一点也非常重要, 它允许你创造宏。
别名
alias是一个命令, 它让用其它字符串替代一句话成为可能。这个命令常常被用来缩短系统命令,或者用来将默认参数加入到常用命令中。
用户个人的别名(alias)最好保存在~/.bashrc
, 而系统级的别名(这些别名会影响所有用户)存放在/etc/bash.bashrc
。
函数
Bash也支持函数。下面这个函数可以解压多种类型的压缩文件。将下面这个函数加入~/.bashrc
中并以这个语法extract
使用它。
~/.bashrc extract() { local c e i (($#)) || return for i; do c='' e=1 if [[ ! -r $i ]]; then echo "$0: file is unreadable: \`$i'" >&2 continue fi case $i in *.t@(gz|lz|xz|b@(2|z?(2))|a@(z|r?(.@(Z|bz?(2)|gz|lzma|xz))))) c='bsdtar xvf';; *.7z) c='7z x';; *.Z) c='uncompress';; *.bz2) c='bunzip2';; *.exe) c='cabextract';; *.gz) c='gunzip';; *.rar) c='unrar x';; *.xz) c='unxz';; *.zip) c='unzip';; *) echo "$0: unrecognized file extension: \`$i'" >&2 continue;; esac command $c "$i" e=$?З done return $e }
注意: Bash用户应该确保extglob功能被打开: shopt -s extglob
, 比如说将它加入到.bashrc
。如果使用Bash completion,这个功能将默认被打开。 Zsh用户应该这样做: 执行setopt kshglob
来替代上面的操作。
另一个实现方式就是安装unp包。
通常进入到另一个目录后我们会用ls来列出目录下的文件。所以我们可以写一个函数来同时做这两件事情。 这个例子中我们把函数命名为'cl'并且会在给定的目录不存在时报错。
~/.bashrc cl() {if [ -d $1 ]; thencd $1lselseecho "bash: cl: $1: Directory not found"fi}
当然ls命令可以被改变以适应你的需求, 比如'ls -hall --color=auto'。
更多bash函数的例子在这里。
提示与技巧
自定义提示符
Bash提示符由变量$PS1
控制。为了让提示符色彩丰富些, 首先要注释掉默认的$PS1
:
#PS1='[\u@\h \W]\$ '
然后加入下面这句:
PS1='\[\e[0;31m\]\u\[\e[m\] \[\e[1;34m\]\w\[\e[m\] \[\e[0;31m\]\$ \[\e[m\]\[\e[0;32m\] '
$PS1
将shell改变成红色的名称和绿色的控制台文本,这对一个root权限的bash提示符十分有用。欲了解更多关于自定义shell的内容, 参阅Color Bash Prompt (简体中文)。
自动命令补全
当你键入一些命令比如sudo时,自动补全功能(在键盘上按Tab
两次)显得尤其有用。
你可以加入以下内容到~/.bashrc
文件中以实现补全功能:
complete -cf your_command
比如说,为了激活sudo和man之后的自动补全功能,可以这样:
complete -cf sudo complete -cf man
高级的补全方法
尽管Bash原生支持基本的文件名,命令和变量的自动补全, 我们仍然可以通过一些方法扩充它的功能。
包bash-completion通过将自动补全扩充到一个更加广泛的的命令和他们的选项中去使自动补全在shell中的表现更加强大。激活高级补全的方法也非常简单,只需要安装这个包就可以:
# pacman -S bash-completion
启动一个新的shell,然后它由于配置文件/etc/bash.bashrc
的作用就会自动激活补全了。
注意: 如果你加入了类似于上文提到的"complete -cf sudo"的设置,并且在Bash自动补全中出现问题,尝试删除那些设置语句。
注意: 通常你使用过去的这些命令操作"$ ls file.*
更快的补全操作
通过加入下面这句话到readline默认的初始化文件(~/.inputrc
或者/etc/inputrc
中):
set show-all-if-ambiguous on
之后没有必要敲击Tab
(默认绑定)两次来产生可能的补全列表(包括有多种补全可能或者没有补全可能时), 因为一次敲击就可以实现。 作为另外一种选择, 产生补全列表只有在没有可能的补全下(比如, 没有多种补全可能时), 将上面的设置语句替换成下面这条:
set show-all-if-unmodified on
命令未找到时的钩子拓展(HOOKS)
包pkgfile包括一个"command not found"的钩子拓展,这个钩子拓展将在你键入未识别命令时自动搜索官方软件仓库。然后显示下面的信息:
chiri ~/docs $ abiword abiword may be found in the following packages: extra/abiword 2.8.6-7 usr/bin/abiword chiri ~/docs $ _
AUR包提供了另外一个"command not found"钩子拓展。command-not-foundAUR, 它会产生像这样的输出:
chiri ~/docs $ abiword
The command 'abiword' is been provided by the following packages: abiword (2.8.6-7) from extra [ abiword ] abiword (2.8.6-7) from staging [ abiword ] abiword (2.8.6-7) from testing [ abiword ]
chiri ~/docs $ _
终端中禁用 Ctrl+z
你可以为你的命令行界面关闭Ctrl+z
(暂停/关闭你的命令行界面程序)的功能通过在这个脚本中包装命令
#!/bin/bash trap "" 20 /path_to_your_application/
例子:
#!/bin/bash trap "" 20 /usr/bin/adom
有了这个例子脚本,当你在玩Adom(游戏)要按Shift+z
组合键时不小心按下了Ctrl+z
组合键,你的游戏就不会停止运行了。其实什么都会发生因为我们已经禁用了Ctrl+z
。
登出后清空屏幕
当登出虚拟终端时,为了实现清屏操作,可以加入下面的语句到~/.bash_logout
:
clear reset
ASCII的艺术, fortunes和cowsay
有了色彩,系统信息和ASCII符号,我们就可以让Bash在登录时展示出一幅ASCII的艺术品。ASCII图片可以在网上找到并粘贴到一个text文件中, 或者通过涂鸦产生。p_w_picpaths can be found online and pasted into a text file, or generated from scratch. To set the p_w_picpath to display in a terminal on login, 将下面的字符串
cat /path/to/text/file
加入~/.bashrc
的顶部。
Bash也可以随机显示一些伤感的,激动人心的,可笑的,讽刺的短句。你可以extra
库中下载安装fortune-mod包来显示一个例子。
--(~)---> fortune It is Texas law that when two trains meet each other at a railroad crossing, each shall come to a full stop, and neither shall proceed until the other has gone.
如果要使短句在登录时随机出现,只需要将下面这句话
command fortune
加入到~/.bashrc
的顶部。
Note: 默认情况下,fortune
显示的引用短语都是无伤大雅的。尽管如此,包里面确实包含了一些无礼的言论,它们放在/usr/share/fortune/off
。你可以查看man手册已得到更多的信息。
这两个功能可以合并在一起,通过这个程序cowsay。改变~/.bashrc
的顶部行来读入下面的命令
command cowsay $(fortune)
或者
command cowthink $(fortune) The earth is like a tiny grain of sand, only much, much heavier. ----------------------------------------- \ ^__^ \ (oo)\_______ (__)\ )\/\ ||----w | || ||
ASCII图像通过.cow
txt文件来生成,它位于/usr/share/cows
中,并且所有的主题可以都可以通过这个命令cowsay -l
来列出。这些文件可以依照用户的喜好进行编辑;自定义的图片可以通过涂鸦和在网上寻找的方式获得。创作一个自定义cow文件的最简方法就是在文本编辑器打开一个存在的.cow
文件,再将浏览器中的ASCII图片复制粘贴到编辑器中,另取名保存即可。你可以用下面的命令测试自定义文件
# cowsay -f cowfile $(fortune)
这个能产生一幅华丽的图画,命令的使用也更加复杂。如果需要更加专业的例子,访问这里。 另外一个例子,这个例子使用了随机产生的cow,随机的脸部表情,并且把fortunes产生文字和图片漂亮的包装在一起。
fortune -a | fmt -80 -s | cowsay -$(shuf -n 1 -e b d g p s t w y) -f $(shuf -n 1 -e $(cowsay -l | tail -n +2)) -n ________________________________________ ( Fry: I must be a robot. Why else would ) ( human women refuse to date me? ) ---------------------------------------- o o o ,'``.._ ,'``. :,--._:)\,:,._,.: :`--,@@@:`...';\ `,'@@@@@@@`---'@@`. /@@@@@@@@@@@@@@@@@: /@@@@@@@@@@@@@@@@@@@\ ,'@@@@@@@@@@@@@@@@@@@@@:\.___,-. `...,---'``````-..._@@@@|:@@@@@@@\ ( )@@@;:@@@@)@@@\ _,-. `. (@@@//@@@@@@@@@@`'@@@@\ : `.//@@)@@@@@@)@@@@@,@; |`. _,'/@@@@@@@)@@@@)@,'@,' :`.`-..____..=:.-':@@@@@.@@@@@_,@@,' ,'\ ``--....-)=' `._,@@\ )@@@'``._ /@_@`. (@) /@@@@@) ; / \ \`-.' (@@@`-:`. `' ___..'@@_,-' |/ `.) `-. `.`.``-----``--,@@.' |/`.\`' ,','); ` (/ (/ (user@host)-(10:10 AM Wed Dec 22)--(~))--->
注意: 如果你想要一幅全色彩的类似于cowsay的艺术图,最好的选择就是ponysay,通过运行命令'ponysay "command or fortune command"',这个包会在你的终端(在X11或者在TTY中你会获得256全色的ponies)里面显示全色彩的小型马(ponies)图片(版本1.1时超过220种),命令'ponysay -l'显示完整的小型马(ponies)的列表。 存在于AUR的一种工具可以用来创作更多的小型马(ponies)的图片(也可创造其它类型),这个工具叫做util-say-gitAUR,而这些新的档案需要存储在$HOME/.local/share/ponysay/ponies和$HOME/.local/share/ponysay/ttyponies,它们分别用在桌面和TTy中。
ASCII历史日历
执行下面命令以安装calendar文件在你的~/.calendar
目录中:
$ mkdir -p ~/.calendar $ curl -o calendar.rpm http://download.fedora.redhat.com/pub/epel/5/x86_64/calendar-1.25-4.el5.x86_64.rpm$ rpm2cpio calendar.rpm | bsdtar -C ~/.calendar --strip-components=4 -xf - ./usr/share/c*
这些会随后显示日历项
$ sed -n "/$(date +%m\\/%d\\\|%b\*\ %d)/p" $(find ~/.calendar /usr/share/calendar -maxdepth 1 -type f -name 'c*' 2>/dev/null);
定制标题
变量$PROMPT_COMMAND
允许你在提示符前执行一个命令。比如说,下面的命令会改变标题为整个当前目录名:
export PROMPT_COMMAND='echo -ne "\033]0;$PWD\007"'
下面的命令会改变你的标题为上一个运行的命令,并且保证你的历史文件总为最新:
export HISTCONTROL=ignoreboth export HISTIGNORE='history*'export PROMPT_COMMAND='history -a;echo -en "\e]2;";history 1|sed "s/^[ \t]*[0-9]\{1,\} //g";echo -en "\e\\";
修正窗口大小调整时的换行
加入你在vi中调整了你的xterm大小,Bash并不会得到resize信号,所以你键入的文本就不会正确的换行,于是它们会重叠提示符。
在/etc/bash.bashrc
(来自Debian)用下面的设置 :
# check the window size after each command and, if necessary, # update the values of LINES and COLUMNS. shopt -s checkwinsize
Bash历史补全
Bash历史补全功能绑定到方向键上(下,上):
# ~/.bashrc bind '"\e[A": history-search-backward'bind '"\e[B": history-search-forward'
或者放在~/.inputrc
:
# ~/.inputrc"\e[A": history-search-backward"\e[B": history-search-forward