Shell脚本和别名命令alias

linux shell有交互式与非交互式两种工作模式。我们日常使用shell输入命令得到结果的方式是交互式的方式,而shell脚本使用的是非交互式方式。

shell提供了alias功能来简化我们的日常操作,使得我们可以为一个复杂的命令取一个简单的名字,从而提高我们的工作效率。在shellalias扩展功能是,因此我们可以键入自己定义的alias别名来执行对应的命令。

alias扩展功能,此时仍然可以定义alias别名,但是shell不会将alias别名扩展成对应的命令,而是将alias别名本身当作命令执行,如果shell内置命令和PATH中均没有与alias别名同名的命令,则shell会“抱怨”找不到指定的命令。

在编写脚本时为了提高脚本的通用性,一般使用linux内置的通用命令,例如ls,cat等. 由于脚本是, 所以在脚本中直接使用系统命令即可。

现在有人要问了,在非交互模式的脚本中如何启用alias扩展呢? 答案是可以使用shell的内置命令shopt来开启alias扩展选项。

shopt的使用
1
2
3
shopt -s opt_name                 Enable (set) opt_name.
shopt -u opt_name Disable (unset) opt_name.
shopt opt_name Show current status of opt_name.

alias扩展功能的选项名称是expand_aliases,我们可以在交互式模式下查看此选项是否开启:

1
2
3
sw@gentoo ~ $ shopt expand_aliases
expand_aliases on
sw@gentoo ~ $

可见在交互式模式下alias扩展功能的确是开启的,因此我们才能使用alias别名。我们编写一个脚本来验证一下非交互式模式下alias扩展的设置:

验证alias扩展
1
2
3
4
5
6
7
8
9
#!/bin/bash --login

alias echo_hello="echo Hello!"
shopt expand_aliases
echo_hello

shopt -s expand_aliases
shopt expand_aliases
echo_hello

执行结果为:

1
2
3
4
5
6
sw@gentoo ~ $ ./test.sh
expand_aliases off
./test.sh: line 5: echo_hello: command not found
expand_aliases on
Hello!
sw@gentoo ~ $

另外,alias别名只在当前shell有效,不能被子shell继承,也不能像环境变量一样export。可以把alias别名定义写在.bashrc文件中,这样如果启动交互式的子shell,则子shell会读取.bashrc,从而得到alias别名定义。但是执行shell脚本时,启动的子shell处于非交互式模式,是不会读取.bashrc的。

如果你一定要让执行shell脚本的子shell读取.bashrc的话,可以给shell脚本第一行的解释器加上参数:

1
#!/bin/bash --login

我们有三种方法可以使脚本变成交互式:

  • --login使得执行脚本的子shell成为一个login shelllogin shell会读取系统和用户的profilerc文件,因此用户自定义的.bashrc文件中的内容将在执行脚本的子shell中生效。
  • 让执行脚本的shell读取.bashrc,在脚本中主动source ~/.bashrc即可。
  • bash脚本首行加上-i参数就变成交互式了,即#!/bin/bash -i.