提供:ZStack云计算
内容介绍
在使用命令行的过程中,相信大家和我一样会越来越强烈地意识到日常使用的大部分命令都只是可用命令中的小小子集。大多数任务的执行过程都已经成为一种习惯,我们会每天以同样的方式加以解决。
尽管多数常见的命令工具都会尽可能缩短名称长度(例如输入‘ls’以代替‘list’,或者‘cd’来代替‘change-directory’)以提升操作效率,但这类用法其实并不太普遍。另外,也有很多人已经习惯于以同样的方式运行命令。
幸运的是,bash允许我们创建自己的命令快捷方式,即为命令创建别名及shell函数。在今天的教程中,我们将探讨如何利用这些选项帮助自己更快完成日常工作。
如何声明一条Bash别名
在bash当中声明别名的过程非常简洁直观。
只需通过以下命令,大家即可完成别名的声明过程,具体语法如其所示:
alias alias_name="command_to_run"
需要注意的是,两个相邻元素与等号之间没有间距。这并非可选方式,空格的加入会破坏该命令。
下面创建一条常用的bash别名。这里选择大家常用的命令,即ls -lha或者ls -lhA(第二条忽略了当前及主目录列表)。我们可以利用以下命令创建这条名为ll的快捷别名:
alias ll="ls -lhA"
现在,我们可以输入ll并列出当前目录中的内容了,其以长格式显示且包含全部隐藏目录:
ll
-rw-r--r-- 1 root root 3.0K Mar 20 18:03 .bash_history
-rw-r--r-- 1 root root 3.1K Apr 19 2012 .bashrc
drwx------ 2 root root 4.0K Oct 24 14:45 .cache
drwx------ 2 root root 4.0K Mar 20 18:00 .gnupg
-rw-r--r-- 1 root root 0 Oct 24 17:03 .mysql_history
-rw-r--r-- 1 root root 140 Apr 19 2012 .profile
drwx------ 2 root root 4.0K Oct 24 14:21 .ssh
-rw------- 1 root root 3.5K Mar 20 17:24 .viminfo
如果大家需要撤销该别名,可直接使用unalias命令:
unalias ll
这样此别名即被撤销。
大家可以直接使用alias命令而不加任何参数以查看全部已配置别名:
alias
要暂时取消全部别名(例如我们为ls -a设定一条ls别名),则可输入:
\ls
这样我们当前路径下将只能使用正常命令,而不会使用其别名版本。
假设大家没有撤销,那么ll别名将可用于当前shell会话。但在打开一个新的终端窗口时,该别名将不会被传递过去。
为了实现通用能力,我们需要将该别名添加到某个shell会话启动时需要加载的文件当中。目前比较流行的选项包括~/.bashrc与~/.bash_profile。我们只需要打开该文件并添加别名即可:
nano ~/.bashrc
将别名添加至命令行中的任意位置。大家可随意添加注释以标记该别名的具体作用:
#########
# Aliases
#########
alias ll="ls -lhA"
我们的文件当中可能已经包含某些别名或者变更。不少发行版都会内置一组标准bash配置文件,其中就包含不少相当实用的别名。
保存并退出文件。大家添加的任何别名都可在启动新shell会话时进行加载。而要在当前会话当中启用文件中的变更,则可要求bash进行re-read:
source ~/.bashrc
别名示例
现在我们已经了解了如何创建自己的别名,接下来要探讨的是如何将其纳入实际使用。部分别名可在网上找到,也有一部分已经默认处于发行版内的bash配置当中。
导航与罗列
在应用部分格式与选项调整之后,相当一部分简单的Linux命令都将变得更加实用。
下面我们以之前提到的ls为例,当然大家也可以自行探寻理想的使用方式。
首先让ls命令在默认条件下采取列式显示并提供文件类型指标(以‘/’结尾的为目录等):
alias ls="ls -CF"
我们也可以加入某些常见的误输入,并使其调用正确的命令:
alias sl="ls"
下面我们还可以精简该别名的输出结果,例如以长格式显示大型目录列表:
alias lsl="ls -lhFA | less"
下面再来看看cd命令可以有哪些延伸。
以下命令会变更我们的主目录——即使我们忘记了具体目录名:
alias cd..="cd .."
大家也可以直接创建一个名为..的别名,将cd部分也精简掉:
alias ..="cd .."
通过设置以下别名,我们可以在当前目录中轻松找到文件:
alias fhere="find . -name "
系统别名
我们是否能够通过这种方式简化某些监控与系统状态命令?我个人也经常使用这些功能,因此为什么不将它们也设置为别名呢?
以下命令将以可人为阅读的形式罗列磁盘使用量,包括文件系统类型,同时在结尾处提供使用总量:
alias df="df -Tha --total"
我们还可以为自己偏好的du输出结果设定别名:
alias du="du -ach | sort -h"
下面依据同样的思路让free输出结果变得更人性化:
alias free="free -mt"
我们可以在罗列进程表时多多利用别名机制。下面先来设置一条默认输出结果:
alias ps="ps auxf"
接下来让进程表具备可搜索性。我们可以创建一条别名,旨在根据我们输入的参数进行进程搜索:
alias psg="ps aux | grep -v grep | grep -i -e VSZ -e"
现在,我们在将所需搜索的进程名作为参数对该命令进行调用时,则会显示以下紧凑的输出结果:
psg bash
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
1001 5227 0.0 0.0 26320 3376 pts/0 Ss 16:29 0:00 bash
其它别名
在使用mkdir命令时,我们往往会为其加上-p以显示全部必要主目录。利用别名机制,我们可以将-p作为其默认参数:
alias mkdir="mkdir -p"
我们可能还需要添加-v,以保证在目录创建时得到通知——这能帮助我们快速了解是否由于输入错误而创建了错误的分支目录:
alias mkdir="mkdir -pv"
在利用wget命令从互联网下载文件时,大家几乎每次都会使用-c来确保出现问题时下载能够继续进行。那么同样将其纳入默认:
alias wget="wget -c"
我们可以使用history命令配合grep轻松进行历史搜索。这种作法在实用性上要远高于使用CTRL-R进行的反向搜索,因为我们可以利用命令参数实现更复杂的回调操作:
alias histg="history | grep"
我手头有不少系统工具,我希望它们能够立足于标准版本进行升级,从而实现更为复杂的功能。我们必须得首先下载对应的功能文件——不过只要用得好,这点小麻烦绝对是值得的。但需要注意的是,其可能会给其它别名带来影响。
这里要替换的是top命令的强化版本——新版本的输出结果更易于阅读,且可对结果进行排序、搜索以及滚动:
alias top="htop"
通过类似的方式,我们可以下载新的ncdu命令以通过交互式ncurses显示我们可浏览的文件与目录大小,亦可用于执行简单的文件操作:
alias du="ncdu"
另有一套df的升级方案,名为pydf。其能够提供彩色输出结果以及基于文本的使用信息栏。在安装完成后,我们可以利用以下命令将其设为默认选项:
alias df="pydf"
大家在路由器之后使用NAT时,是否曾希望通过命令行获取当前公共IP地址?以下别名将大大简化获取过程:
alias myip="curl http://ipecho.net/plain; echo"
在实际使用中,我倾向于将自己的文章上传图片优化为690像素或者更低水平,因此我会使用ImageMagick软件包(如果大家还没有安装该软件包,可运行sudo apt-get install imagemagick),其中包含一条名为mogrify的命令。我将这条命令添加到了自己的~/.bashrc文件当中:
alias webify="mogrify -resize 690\> *.png"
其会将当前目录中全部宽度超过690像素的PNG图像进行尺寸调整。
接下来要做的就是将其上传至服务器了,我可以使用sftp连接并自动变更至特定目录:
alias upload="sftp username@server.com:/path/to/upload/directory
Bash函数入门
虽然别名机制非常便捷且易于实现,但其作用仍然比较有限。大家可能会发现自己需要执行某些连锁操作,而且很难单纯利用添加参数的方式实现。另外,别名的运行速度也不理想——因为其运行优先级低于全部函数。
我们还有另一种解决方案,其更为强大且能够帮助大家弥合bash别名与完整shell脚本之间的空白,这就是所谓shell函数。它们的作用方式同别名一样,但更具扩展性且能够以标准方式接收输入内容。
这里我们不会讨论过于详尽的细节,因为其中可能涉及大量非常复杂的情况,而bash本身又是一种完整的脚本语言——不过我们可以通过几个基本示例进行讲解。
对于入门者,我们可以利用两种基本方式声明一条bash语法。其一为使用function命令,具体如下:
function function_name {
command1command2
}
另一种则是使用与C语言非常类似的几组括号:
function_name () {
command1command2
}
我们也可以将第二种形式压缩为一行,并用分号隔开各命令。其中最后一条命令必须以分号结尾:
function_name () { command1; command2; }
下面演示几条非常实用的bash函数。下面这条将创建一个目录,而后立即进入该目录。我们在管理新目录时肯定经常用到:
mcd () {
mkdir -p $1
cd $1
}
现在,当我们使用该函数来取代常见的mkdir命令时,其会在目录创建完成后自动进入此目录:
mcd test
pwd
/home/demouser/test
另一条极具实用性的函数则为extract。其中集成了大量功能,允许我们解压几乎所有格式的压缩文件。其存在大量变种,不过这里建议大家使用这一条:
function extract {
if [ -z "$1" ]; then
# display usage if no parameters given
echo "Usage: extract <path/file_name>.<zip|rar|bz2|gz|tar|tbz2|tgz|Z|7z|xz|ex|tar.bz2|tar.gz|tar.xz>"
else
if [ -f $1 ] ; then
# NAME=${1%.*}
# mkdir $NAME && cd $NAME
case $1 in
*.tar.bz2) tar xvjf ../$1 ;;
*.tar.gz) tar xvzf ../$1 ;;
*.tar.xz) tar xvJf ../$1 ;;
*.lzma) unlzma ../$1 ;;
*.bz2) bunzip2 ../$1 ;;
*.rar) unrar x -ad ../$1 ;;
*.gz) gunzip ../$1 ;;
*.tar) tar xvf ../$1 ;;
*.tbz2) tar xvjf ../$1 ;;
*.tgz) tar xvzf ../$1 ;;
*.zip) unzip ../$1 ;;
*.Z) uncompress ../$1 ;;
*.7z) 7z x ../$1 ;;
*.xz) unxz ../$1 ;;
*.exe) cabextract ../$1 ;;
*) echo "extract: '$1' - unknown archive method" ;;
esac
else
echo "$1 - file does not exist"
fi
fi
}
这条函数会提取第一条参数并调用与文件扩展名对应的解压程序。
总结
希望今天的教程能为大家提供创建别名与bash函数的灵感。使用这些方案能够帮助大家显著提升日常工作效率。
请记住,重新定义现有命令的操作方式具有一定潜在破坏性。另外,如果大家已经习惯了使用某些自定义别名,那么一旦切换到其它设备环境,则可能产生强烈的不适感~
如果大家在考虑应选择哪些命令来创建别名,不妨首先查看常用命令历史记录。大家不妨参阅此处以了解通常情况下使用频率最高的命令:
history | awk '{CMD[$2]++;count++;}END { for (a in CMD)print CMD[a] " " CMD[a]/count*100 "% " a;}' | grep -v "./" | column -c3 -s " " -t | sort -nr | nl | head -n10
1 247 24.7% cd
2 112 11.2% vim
3 90 9% exit
4 72 7.2% ls
5 70 7% xset
6 56 5.6% apt-get
7 40 4% vlc
8 40 4% rm
9 38 3.8% screen
10 27 2.7% htop
我们可以利用这份清单快速为常用命令创建别名。大家也不妨在评论中分享您最偏好的bash别名与函数:)
本文来源自DigitalOcean Community。英文原文:An Introduction to Useful Bash Aliases and Functions By Justin Ellingwood
翻译:diradw