Linux深度攻略
上QQ阅读APP看书,第一时间看更新

2.5 Shell实用功能

Shell的实用功能主要有命令行自动补全、命令历史记录、命令排列、命令替换、命令别名、文件名匹配和管道。

2.5.1 命令行自动补全

在Linux系统中,有太多的命令和文件名称需要记忆,使用命令行补全功能可以快速地写出文件名和命令名。

如果需要快速地从当前所在的目录跳转到/usr/src/kernels/目录,可以执行以下操作。

[root@rhel ~]# cd /u<Tab>/sr<Tab>/k<Tab>

<Tab>是按[Tab]键的意思,使用[Tab]键也称为命令行自动补全,这在平常应用中是不可缺少的。

让我们仔细看看这个例子。

[root@rhel ~]# cd /u<Tab>

扩展成了“cd /usr/”,再按[Tab]键,如下所示,扩展为“cd /usr/src/”。

[root@rhel ~]# cd /u<Tab>/sr<Tab>

因此,使用[Tab]键可以很方便地根据前几个字母来查找匹配的文件或子目录。

2.5.2 命令历史记录

在操作Linux系统的时候,每一个操作的命令都会被记录到命令历史中,在以后可以通过命令历史查看和使用以前操作的命令。

1.和命令历史有关的变量

bash启动的时候会读取~/.bash_history文件,并将其载入到内存中。$HISTFILE变量用于设置~/.bash_history文件,bash退出时也会把内存中的历史记录回写到~/.bash_history文件中。

例2.15:显示$HISTFILE变量的值。

[root@rhel ~]# echo $HISTFILE

/root/.bash_history

在/etc/profile 文件文件中,默认定义了1000个命令历史记录,如下所示。

[root@rhel ~]# cat /etc/profile |grep HISTSIZE

HISTSIZE=1000

下面介绍一下$HISTSIZE和$HISTFILESIZE变量。

● $HISTSIZE:设置bash会话期间命令历史包含的命令数量;

● $HISTFILESIZE:设置历史文件中实际存储的命令数量。

例2.16:显示$HISTSIZE和$HISTFILESIZE变量的值。

[root@rhel ~]# echo $HISTSIZE

1000

[root@rhel ~]# echo $HISTFILESIZE

1000

2.使用命令历史

使用history命令可以查看命令历史记录,每一条命令前面都会有一个序列号标示。

命令语法:

history [选项]

命令中各选项的含义如表2.13所示。

表2.13 history命令选项的含义

在Linux系统中使用命令历史的举例如表2.14所示。

表2.14 使用命令历史的举例

通过表2.15所示的快捷键可以非常方便地搜索历史命令。

表2.15 搜索历史命令

例2.17:使用命令历史记录功能键。

[root@rhel ~]# mkdir /root/aaa

//创建目录/root/aaa

[root@rhel ~]# cd !$

cd /root/aaa

//!$是指重复前一个命令最后的参数,参数是/root/aaa

[root@rhel aaa]# pwd

/root/aaa

//显示用户当前目录是/root/aaa

例2.18:查看命令历史记录。

[root@rhel ~]# history

//显示过去曾经输入过的命令,只有两列信息:编号和命令

例2.19:显示执行过的前两条命令。

[root@rhel ~]# history 2

//在这里使用history +2和history 2命令起到的效果一样

例2.20:查看/root/.bash_history文件。

[root@rhel ~]# cat /root/.bash_history

例2.21:将当前的历史命令写入.bash_history文件。

[root@rhel ~]# history-w

例2.22:将目前新增的 history 历史命令写入.bash_history文件。

[root@rhel ~]# history-a

例2.23:清空命令历史记录。

[root@rhel ~]# history-c

//清空命令历史记录以后,再次使用history命令已经无法查看以前的命令历史

2.5.3 命令排列

如果希望一次执行多个命令,Shell允许在不同的命令之间放上特殊的排列字符。命令排列可以使用两种排列字符:“;”和“&&”。

1.使用“;”

使用“;”命令时先执行命令1,不管命令1是否出错,接下来就执行命令2。

命令语法:

命令1;命令2

例2.24:使用排列命令“;”同时执行两个命令。

[root@rhel ~]# ls /boot;du-hs /root

config-3.10.0-327.el7.x86_64

extlinux

grub2

initramfs-0-rescue-695707d564a94beba0e784062566b7e0.img

initramfs-3.10.0-327.el7.x86_64.img

initramfs-3.10.0-327.el7.x86_64kdump.img

initrd-plymouth.img

symvers-3.10.0-327.el7.x86_64.gz

System.map-3.10.0-327.el7.x86_64

vmlinuz-0-rescue-695707d564a94beba0e784062566b7e0

vmlinuz-3.10.0-327.el7.x86_64

4.4 M  /root

//先在屏幕上列出/boot目录中的所有内容,然后列出目录/root及其子目录所占用的磁盘空间大小

2.使用“&&”

使用“&&”命令时,只有当命令1正确运行完毕后,才能执行命令2 。

命令语法:

命令1&&命令2

例2.25:使用排列命令“&&”同时执行两个命令。

[root@rhel ~]# ls-a /root/bogusdir&&du-sh

ls: 无法访问/root/bogusdir: 没有那个文件或目录

//将返回“ls: 无法访问/root/bogusdir: 没有那个文件或目录”,而“du-sh”命令根本没有运行,因为第一个命令都没有成功执行

2.5.4 命令替换

在Linux系统中,Shell命令的参数可以由另外一个命令的结果来替代,这种操作称为命令替换。

命令替换可以使用两种替换字符:“$( )”和“``”。

1.使用“$( )”

命令语法:

命令1 $(命令2)

下面讲解一个例子。

结束一个名为less的进程前先得用命令pidof找出相应的进程号,然后以这个进程号为参数,运行kill命令,这样就可以结束less进程,使用以下命令。

[root@rhel ~]# pidof less

7552

//less进程号为7552

[root@rhel ~]# kill-9 7552

//结束进程号为7552的进程(也就是less进程)

例2.26:使用命令替换功能结束less进程。

[root@rhel ~]# kill-9 $(pidof less)

// pidof less命令的输出7552作为命令kill-9的参数,然后就可以结束该进程了

2.使用“``”

除了可以使用“$()”之外,还可以使用后引号“'”(位于Tab键上面那个键)。

命令语法:

命令1 '命令2'

这样虽然可以减少输入,但可读性差,而且很容易和没有替换功能的一般单引号混淆。

例2.27:使用命令替换功能结束less进程。

[root@rhel ~]# kill-9 'pidof less'

2.5.5 命令别名

在需要执行某一个非常长的命令时,所有的命令以及命令的选项、参数都要一一输入,很枯燥也容易出现错误。可以为常用命令定义快捷方式,这些快捷方式可以用比较简单的命令别名来定义。

1.创建别名

使用alias命令可以为命令定义别名。如果命令中有空格的话,就需要使用双引号(比如在命令与选项之间就有空格)。

命令语法:

alias [别名]=[需要定义别名的命令]

例如,使用下面的命令查看/boot目录的内容。

[root@rhel ~]# ls /boot

显然,如果每次需要查看/boot目录的内容都要输入这样的命令,会非常麻烦,因此可以定义别名。

例2.28:为ls /boot命令创建别名ok。

[root@rhel ~]# alias ok="ls /boot"

[root@rhel ~]# ok

config-3.10.0-327.el7.x86_64

extlinux

grub2

initramfs-0-rescue-695707d564a94beba0e784062566b7e0.img

initramfs-3.10.0-327.el7.x86_64.img

initramfs-3.10.0-327.el7.x86_64kdump.img

initrd-plymouth.img

symvers-3.10.0-327.el7.x86_64.gz

System.map-3.10.0-327.el7.x86_64

vmlinuz-0-rescue-695707d564a94beba0e784062566b7e0

vmlinuz-3.10.0-327.el7.x86_64

//在终端中输入别名ok就可以查看/boot目录的内容

例2.29:查看系统中所有的别名。

[root@rhel ~]# alias

alias cp='cp-i'

alias egrep='egrep--color=auto'

alias fgrep='fgrep--color=auto'

alias grep='grep--color=auto'

alias l.='ls-d .*--color=auto'

alias ll='ls-l--color=auto'

alias ls='ls--color=auto'

alias mv='mv-i'

alias ok='ls /boot'

alias rm='rm-i'

alias which='alias | /usr/bin/which--tty-only--read-alias--show-dot--show-tilde'

//有些别名(比如cp、ll、ls、mv、rm、which)是系统定义的,有些别名(比如ok)是用户定义的

2.取消别名

当用户需要取消别名的定义时,可以使用unalias命令。

命令语法:

unalias [别名]

例2.30:取消之前定义的别名ok。

[root@rhel ~]# unalias ok

[root@rhel ~]# ok

bash: ok: 未找到命令...

//取消别名之后不能使用别名ok了

在重新启动计算机系统以及关闭终端以后,定义的别名会失效。若系统中有一个命令,同时定义了一个与其同名的别名,则别名将优先于系统中原有的命令而执行。

注意:

如果希望重新启动计算机系统以及关闭终端以后,定义的别名仍旧生效,可以编辑/etc/bashrc(针对系统中所有用户)或$HOME/.bashrc(针对某一个指定用户,$HOME代表用户主目录)文件,将别名定义命令写到这两个文件中。

2.5.6 文件名匹配

文件名匹配使得用户不必一一写出文件名称就可以指定多个文件。这将用到一些特殊的字符,称之为通配符。

1.通配符“*”

“*”可匹配一个或多个字符。假设想用rm命令删除当前目录下所有以字符串“.bak”结尾的文件,除了在rm命令后面写上所有文件名作为参数,还可以使用通配符“*”,使用以下命令。

[root@rhel ~]# rm *.bak

在本例中,告诉Shell将命令rm的参数扩展到所有以“.bak”结尾的文件,Shell就将扩展后的参数告诉rm命令。Shell在命令执行前,将读取并解释命令行。

假如当前目录下,包含文件124.bak、346.bak和583.bak。如果只想保留文件583.bak,将其余两个文件删除,可以使用以下命令。

[root@rhel ~]# rm *4*.bak

Shell就将“*4*.bak”扩展成所有含“4”并以“.bak”结尾的字符串。

2.通配符“?”

第二个通配符是“?”。在匹配时,一个问号只能代表一个字符。为了示范其用途,我们在上例的假设中另外再添加311.bak和abcd.text两个新文件。现在,列出所有在“.”后有4个字符的文件,使用以下命令。

[root@rhel ~]# ls *.????

abcd.text

2.5.7 管道

Linux系统的理念是汇集许多小程序,每个程序都有特殊的专长。复杂的任务不是由大型软件完成,而是运用Shell 的机制,组合许多小程序共同完成。管道就在其中发挥着重要的作用,它可以将某个命令的输出信息当作某个命令的输入,由管道符号“|”来标识。

命令语法:

[命令1]|[ 命令2]|[ 命令3]

例2.31:使用简单的管道。

[root@rhel ~]# ls /etc|more

abrt

adjtime

akonadi

aliases

aliases.db

alsa

...(省略)

cgconfig.conf

cgconfig.d

cgrules.conf

cgsnapshot_blacklist.conf

chkconfig.d

chrony.conf

--More-

//命令ls /etc显示/etc目录的内容,命令more是分页显示内容

例2.32:使用复杂的管道。

[root@rhel ~]# rpm-qa|grep a|more

//命令rpm-qa显示已经安装在系统上的RPM包,命令grep a是过滤软件包,命令more是分页显示这些信息