在操作 Linux 的過程中,最令你感到不爽的是什麼?答:命令太多,選項太多,記不住。
命令可以通過本書學習,但選項太多可真的不好辦了,我想即便是 Linux 大牛們,也不可能記住每個命令的所有選項吧。
幸好 Linux 系統中有一個叫作 alias 的命令,它可以給一些命令設定別名,利用它我們就可以不必記住太多複雜的選項,只需將這些選項設定成別名就好啦。
定義別名
定義別名的方法很簡單,格式如下所示:
alias [name[=value]]
這裡需要注意的是:
-
等號(=)前後不能有空格,否則就會出現語法錯誤了。
-
如果value中有空格或tab,則value一定要使用引號(單、雙引號都行)括起來。
了解了別名的基礎知識之後,我們來看一個定義別名的例子:
[[email protected] ~]$ alias vi='vim'
這個例子定義了一個 vim 命令的別名,以後,當我們執行 vi 命令時,其實真正執行的是 vim 命令。是不是很簡單呢!
如何檢視別名
如果太熱衷於設定別名,那麼你就會面臨著要記住很多別名的困擾,因此,學會檢視所有已設定的別名,就顯得尤為重要了。
檢視別名的方法也很簡單,直接輸入 alias 命令,不加任何選項和引數即可:
[[email protected] ~]$ alias
alias cp='cp -i'
alias l.='ls -d .* --color=auto'
alias ll='ls -l --color=auto'
alias ls='ls --color=auto'
alias mv='mv -i'
alias rm='rm -i'
alias vi='vim'
alias which='alias | /usr/bin/which --tty-only --read-alias --show-dot --show-tilde'
可以看到,系統把當前可用的所有的別名都列出來了。仔細找一下,是不是可以看到剛才設定的那個別名了:alias vi='vim'。
檢視單獨命令的別名
如果我們只想檢視一個單獨命令是否設定了別名,那麼方法有兩個。
方法一:使用 alias 命令加引數
[[email protected] ~]$ alias vi
alias vi='vim'
方法二:使用快捷鍵
當在終端中輸入一個命令後,按下 Ctrl+Alt+E 組合鍵,假如設定了別名,那麼別名自動會變成實際的命令。
注意:這個快捷鍵並非在所有終端中都可行,有些終端的快捷鍵會和這個快捷鍵衝突,這樣的話,該方法就不好使了。
如何取消別名
別名定義的太多了,往往帶來的不是方便,而是困擾。所以我們也需要掌握刪除別名的方法。
那麼,如何刪除一個別名呢?可以使用 unalias 命令。比如,我們想刪除 vi='vim' 這個別名,可以這樣來操作:
#刪除別名設定
[[email protected] ~]$ unalias vi
#再看看, 已經被刪除了吧
[[email protected] ~]$ alias
alias cp='cp -i'
alias dirA='echo work directory is /root'
alias dirB='echo work directory is $PWD'
alias l.='ls -d .* --color=auto'
alias ll='ls -l --color=auto'
alias ls='ls --color=auto'
alias mv='mv -i'
alias rm='rm -i'
alias which='alias | /usr/bin/which --tty-only --read-alias --show-dot --show-tilde'
經過仔細觀察,確實已經找不到剛才定義的 vi 別名了。
如果你想刪除所有的別名,直接使用 unalias 命令的-a選項即可,只不過要謹慎使用,避免你設定的所有的別名一下子都被清除了,自己還得一個一個重新設定回來。
#刪除所有別名
[[email protected] ~]$ unalias -a
#空空如也
[[email protected] ~]$ alias
如何執行命令本身而非別名
別名雖好,但也有它的弊端,比如定義的別名恰好和某個命令重名了,這就麻煩了,Shell 中執行的將永遠都是別名。這裡,如果我們想執行真正的那個命令而非別名,該怎麼辦呢?有三種方法可以解決這個問題:
-
方案一:使用命令的絕對路徑。
-
方案二:切換到命令所在的目錄,執行./command。
-
方案三:在命令前使用反斜線()。
下面我們就通過範例來演示這三個方法:
#絕對路徑方法
[[email protected] ~]$ /bin/vi test.sh
#明確指定當前路徑的方法
[[email protected] ~]$ cd /bin
[[email protected] bin]$ ./vi ~/test.sh
#使用反斜線的方法
[[email protected] bin]$ cd
[[email protected] ~]$ vi test.sh
這裡推薦大家使用最後一種方法,因為它既方便又實用。
如何讓別名永久有效
我們通過 alias 命令設定的別名,僅限於在當前的 Shell 中使用,如果系統重新啟動了,那麼新設定的別名就失效了。
如果想讓別名永久有效的話,就需要把所有的別名設定方案加入到($HOME)目錄下的 .alias 檔案中(如果系統中沒有這個檔案,你可以建立一個),然後在 .bashrc 檔案中增加這樣一段程式碼:
# Aliases
if [ -f ~/.alias ]; then
. ~/.alias
fi
這樣設定後,無論怎樣重新啟動系統,都不會影響設定的別名啦。
單引號和雙引號的困惑
在別名的應用中,單引號和雙引號的使用是比較容易造成困惑的,請看下面的範例:
[[email protected] ~]$ echo $PWD
/root
[[email protected] ~]$ alias dirA="echo work directory is $PWD"
[[email protected] ~]$ alias dirB='echo work directory is $PWD'
# 正確顯示
[[email protected] ~]$ dirA
work directory is /root
# 正確顯示
[[email protected] ~]$ dirB
work directory is /root
# 顯示不正確, 怎麼回事?
[[email protected] ~]$ cd /
[[email protected] /]$ dirA
work directory is /root
# 正確顯示
[[email protected] /]$ dirB
work directory is /
上面的程式最讓人困惑的是,別名中使用了 Shell 的系統變數 $PWD 來顯示當前的目錄路徑,但當目錄切換了之後,單引號的別名可以正常顯示,而雙引號的別名卻無法正常顯示了,這和我們使用 bash 的變數的經驗正好相反。這是怎麼回事呢?
其實問題的本質在於,別名只是用來替代我們設定的命令。
下面就來看看 dirA 和 dirB 背後的真實面容:
[[email protected] ~]$ alias dirA
alias dirA="echo work directory is /root"
[[email protected] ~]$ alias dirB
alias dirB='echo work directory is $PWD'
看到了吧,使用雙引號的 dirA,通過 Shell 的變數轉換後已經變成了字串 echo work directory is/root,當目錄切換後,當然還是顯示字串的內容。而使用單引號的 dirB,由於不受 Shell 的影響,仍然保留著原來的設定 echowork directory is$PWD,當切換目錄後再執行,變數 $PATH 被 Shell 替換掉,因此,內容被正確顯示了。
在 Shell 指令碼中執行別名的困惑
在 Shell 指令碼中,alias 別名功能預設是關閉的,如果將 alias 別名編寫到指令碼中,而此時 Shell 內建命令和 PATH 中均沒有與 alias 別名同名的命令,則 Shell 會“抱怨”找不到指定的命令。就像下面的例子中展示的一樣:
[[email protected] ~]$ cat test.sh
#!/bin/bash
ll
[[email protected] ~]$ ./test.sh
./test.sh: line 3: ll: command not found
有沒有辦法在 Shell 指令碼中啟用 alias 別名功能呢?答案是有的,那就是使用 Shell 內建的 shopt 命令來開啟 alias 別名擴充套件選項 expand_aliases。我們現在就來試驗一下:
[[email protected] ~]$ shopt -s expand_aliases
[[email protected] ~]$ shopt expand_aliases
expand_aliases on
[[email protected] ~]$ ./test.sh
./test.sh: line 3: ll: command not found
悲劇,怎麼還是提示同樣的錯,難道被忽悠了?不急,我們來分析一下,找出問題的原委:
[[email protected] ~]$ cat test.sh
#!/bin/bash
shopt expand_aliases
ll
[[email protected] ~]$ ./test.sh
expand_aliases off
./test.sh: line 5: ll: command not found
從我們的試驗中可以看出,上面程式執行失敗的原因是:雖然在 Shell 中 expand_aliases 是 on 狀態,但當執行 test.sh 時,會產生一個新的進程去執行,這個新的進程中 expand_aliases 卻是 off 的狀態。
知道了這個原因,我們做出相應修改,繼續試驗:
[[email protected] ~]$ cat test.sh
#!/bin/bash
shopt expand_aliases
shopt -s expand_aliases
shopt expand_aliases
ll
[[email protected] ~]$ ./test.sh
expand_aliases off
expand_aliases on
./test.sh: line 8: ll: command not found
這一次我們在指令碼中強制把 expand_aliases 設定為 on 狀態,這次應該沒有問題了吧。但事與願違,別名在指令碼中仍然不生效。
作為一名合格的工程師,我們要有打破砂鍋問到底的精神,控制住幾近崩潰的情緒,我們繼續做試驗:
[[email protected] ~]$ cat test.sh
#!/bin/bash
##
shopt expand_aliases
shopt -s expand_aliases
shopt expand_aliases
alias
ll
[[email protected] ~]$ ./test.sh
expand_aliases off
expand_aliases on
./test.sh: line 10: ll: command not found
又發現了新情況,alias 命令竟然沒有輸出任何內容!這還是執行程式時新生成進程的問題。從現象來看,應該是指令碼中的 alias 沒有繼承 Shell 中 alias 的設定內容。
不賣關子啦,我們揭曉最終的答案,解決方法是使用 bash 的 --login 選項:
[[email protected] ~]$ cat test.sh
#!/bin/bash --login
##
shopt expand_aliases
shopt -s expand_aliases
shopt expand_aliases
alias
ll
[[email protected] ~]$ ./test.sh
expand_aliases off
expand_aliases on
alias list is
alias cp='cp -i'
alias l.='ls -d .*'
alias ll='ls -l'
alias mv='mv -i'
alias rm='rm -i'
alias which='alias | /usr/bin/which --tty-only --read-alias --show-dot --show-tilde'
total 12
-rw-r--r-- 1 roc roc 740 Feb 5 16:21 cat.time.txt
-rwxr--r-- 1 roc roc 131 Feb 6 17:15 test1.sh
-rwxr--r-- 1 roc roc 121 Feb 6 17:45 test.sh
功夫不負有心人,這次終於執行成功了!
bash 的 --login 選項的作用是使執行指令碼的子 Shell 成為一個 login Shell,而 login Shell 就會讀取系統和使用者的 profile 及 rc 檔案,這樣就會順理成章地載入到 alias 的初始設定啦。