新建一個文本文件包含所需要的腳本。舉例,我會使用pico編輯器寫一個腳本用來運行程序tar,帶上必要的可選項可以用來解壓從因特網下載下來的*.tar的文件(我好像總是記不住tar的所有參賽)。我決定把我的腳本名稱叫做“untar”:
pico untar
因為在我的當前工作目錄里untar文件不存在,所有pico文本編輯器自動創建這個文件,現在,我輸入以下內容:
#!/bin/bash
echo this is the script file $0
echo untarring the file $1
# this calls tar with options -xvzf (extract,
# verbose, filter through gzip, input filename)
tar -xvzf $1
我使用<CTRL>O保存這個文件,然后<CTRL>X退出。
腳本的第一行,以“#!”開始是特別的提示-它告訴shell應該用哪一個程序來解釋我的腳本。在這個例子里,我使用bash shell /bin/bash。第一行必須使用“#!”開頭,否則腳本不會運行(系統認為是一個文本文件)。其他以“#”開始的行是注釋行只是給作者和讀者使用的,計算機將跳過這些行。
在以上腳本里,參數$0, $1, $2…是傳遞到腳本里面的參數。舉個例子,如果我運行我的腳本名“myscript”帶七個參數如下:
myscript a b c d e f g
那么,參賽$0就是myscript, $1就是a, $2就是b,$3就是c,依此類推。
腳本的第二行和第三行,echo命令輸出所有在它后面同一行上的文本,然后擴展在腳本里對應的參數$0和$1。第四行和第五行是我寫的注釋文本,提醒我在這個腳本里要做的事情。只有最后一行是真正起作用的。
一旦腳本已經寫好,我把文件屬性改成對文件擁有者是“可執行”的:
chmod u+x untar
然后我的腳本就可以這樣運行了:
./untar my_tar.tar.gz
Liunx腳本的確非常豐富,靈活,功能強勁,還可能有點復雜。然而,對于日常任務編寫一些簡單腳本,它并不需要什么特別高深的知識。你可以把一些要用到的命令放在一起,一個接一個,輸入到文件里。我使用腳本很頻繁是因為我太懶了,不想一次一次的輸入相同的命令。
一個最簡單的方法,可以把一組命令放在文本文件里然后使用source命令傳遞給shell讓它直接運行:
source my_file
這個時候就不需要在文本第一行加上“#!”的標志了。
3.4.6? 引號的含義
?
一般來說,以下字符對于shell有特殊的含義:
\ ' " ` < > [ ] ? | ; # $ ^ & * ( ) = <Space> <Tab> <Newline>
這里有四種不同的符號:反斜杠(\),單引號(‘),雙引號(“),反向單引號(`)。
?反斜杠(\)表示:關閉后面字符的特殊含義?
?單引號(‘)表示:關閉在兩個單引號之間所有字符的特殊含義?
?雙引號(“)表示:關閉在兩個雙引號之間所有字符的特殊含義除了$ ` \?
?反向單引號(`)表示:告訴shell首先運行兩個反向單引號之間的命令,然后把得到的結果再傳遞給兩個單引號之外的命令。同樣的功能也可以通過“$command”命令來實現,而且可能會更方便。?
舉個例子,我可以創建一個奇怪的目錄名叫做“*”通過使用“\”或者“’”符號:
mkdir \*
mkdir ’*’
這屏蔽了“*”對于shell的特別含義。如果沒有“\”,“*”意味著當前目錄下所有文件。
3.4.7? 輸入輸出重定向
?
有三個最重要的輸入輸出流:標準輸入(stdin),標準輸出(stdout),標準錯誤(stderr)。它們對于控制臺(“控制臺”指的是鍵盤用于輸入,屏幕用于輸出)來說是缺省的,但是它們可以被重定向。
重定向標準輸出,可以使用“>”符號,舉例:
dir my_dir > filelisting.txt
將把dir命令的標準屏幕輸出重定向到文本文件 filelisting.txt文件里,所以屏幕上沒有任何輸出。這個文件可以用來編輯(比如使用pico文本編輯器)或者合并到其他的文件里。
重定向標準錯誤,可以使用結構“2>”,舉例:
dir my_dir 2> errorlisting.txt
以上命令將送標準輸出到屏幕上,如果沒有錯誤信息,將沒有任何信息寫到errorlisting.txt文件里。如果出錯,則沒有什么東西輸出到屏幕,而文件errorlisting.txt將包含錯誤信息。錯誤信息有可能是這樣的:
dir: my_dir:? Permission denied
最后,我也可以把標準輸出和標準錯誤一起輸出到同一個文件里,
dir my_dir > file_and_error_listing.txt 2>&1
以上命令先重定向標準輸出到文本文件里,然后再重定向標準錯誤到和標準輸出同樣的位置。它如何實現可能看起來有點古怪,但是是可行的。
在以上的例子里,如果重定向的文件已經存在,該文件會被覆蓋。如果你要追加到該文件的末尾,可以使用“>>”符號,以上的例子就變成:
dir my_dir >> filelisting.txt
dir my_dir 2>> errorlisting.txt
dir my_dir >> file_and_error_listing.txt 2 > &1
如果你對“2>”感到很迷惑,這里有一個簡單的辦法可以幫你理解,標準流有標準的解析器:“0”代表標準輸入,“1”代表標準輸出,“2”代表標準錯誤。
dir my_dir > file.txt
是以下命令的簡寫方式:
dir my_dir 1 > file.txt
那么以下命令就是用來輸出標準錯誤:
dir my_dir 2 > file.txt
還有,你還可以使用符號“|”(管道命令)把一個命令的標準輸出送到另外一個命令的標準輸入。在以下這個標準的例子里,dir命令的標準輸出通過管道輸入到命令more里(輸出滿屏的時候自動暫停):
dir | more
你還可以使用“tee”命令把標準輸出同時寫到文件和屏幕,
dir | tee filelisting.txt
tee是“T型連接器”的模擬音,在管道中的主要的用途是分流。
這個部分這樣都用來講述標準輸出重定向,對于標準輸入重定向不像標準輸出重定向那么有用,但是它可以使用以下方式實現:
cat < my_file
還有一種叫做“直接插入式”的標準輸出,可以通過“<<”來實現。不要管它了,看起來對我沒有什么實際用處。不過,如果你真的想知道,這里有一個例子(這里“>”式第二個提示符)
cat << my_marker
> my_line_from_the_keyboard
> another_line_from_the_keyboard
> my_marker
除了重定向到常規文件和“過濾器”之外(如以上的例子所示),你還可以重定向到設備和其他特殊文件。看下面這些例子。
重定向到設備文件的例子。以下命令將顯示文件列表到第四個文本終端:
dir > /dev/tty4
以下是一個重定向到一個特殊的FIFO(先進先出)文件的例子。該命令送信息”you are lucky”到叫做“lucky”的ICQ用戶UIN 7777777 (假定你已經用你的ICQ程序連接到ICQF服務器上了)
echo message 7777777 “you are lucky” < ~/.licq/licq_fifo
以上的例子能夠工作是因為在你licq目錄下的文件“licq_fifo”是一個特別的FIFO序列文件。以上這個例子,對比于在圖形用戶界面下的ICQ程序有什么特別有用的地方嗎?舉個例子,你可以寫一個短的腳本帶上多個信息給你的那些ICQ伙伴們:
#!/bin/bash
echo Messaging UIN: $1 Message: $2 Times: $3
# The next command puts puts your licq in the status "on-line, invisible".
echo 'status *online' > ~/.licq/licq_fifo
c=0
while [ $c -le $3]
do
echo message $1 $2 > ~/.licq/licq_fifo
c=`expr $c + 1`
echo $c " "
done
echo 'status offline' > ~/.licq/licq_fifo
echo "all done"
這個例子利用了licq通信模型(FIFO文件)和簡單的文件重定向功能,給你一個關于如何 “自動化”licq的主意。
3.4.8? Shell的特殊字符(metacharacters)
?
一般來說,這些字符對于shell有特別的含義:
\ ' " ` < > | ; <Space> <Tab> <Newline> ( ) [ ] ? # $ ^ & * =
以下是這些字符的含義:
\ ‘ “ 和 ‘ 主要用來注釋,前面已經描述過 (參見 3.4.6)。
< 和 > 主要用來輸入和輸出重定向
| 是管道命令,管道左邊的標準輸出是管道右邊的標準輸入
; 用于間隔在同一命令行上的幾個命令
<Space> 和 <Tab> 間用于分開命令的字符和單詞
<Newline> 完成一條命令或者一組命令
( ) 用于封裝需要使用不同的shell啟動的命令, 比如 ( dir )
{ } 用于封裝要用當前shell啟動的一組命令,比如 { dir },需要空格間隔
& 使當前命令在后臺運行(有它自己獨立的進程),所以下一條命令不需要等待前一條命令結束才能開始。
* 當搜索文件時,它匹配除了以“.”開頭的所有文件
?當搜索文件時,它匹配任何單個字符
[ ] 當搜索文件時,它匹配任何在[]里面的單個字符
&& 是用于連接兩個命令的“與操作”,
command1 && command2, 只有當command1退出狀態為0時(沒有錯誤),command2才會被執行。比如, cat file1 && cat file2 只有當file1正常顯示時, file2才能被顯示。
||? 是用于連接兩個命令的“或操作”
command1 || command2, 只有當command1退出狀態非0時(有錯誤),command2才會被顯示。比如:cat file1 || cat file2 只有當顯示file1出錯時,file2才能被顯示
= 指定值給變量
舉例,命令me=blahblah設定值“blahblah”給變量“me”,我可以輸出變量名:
echo $me
$????? 預處理擴展變量名
變量可以使用“=”來設定值,也可以通過預先變量設定來設置
$0???? 被執行的shell腳本的名稱
$#???? 按位置對應的命令輸入參數, $1第一個參賽, $2第二個參數, $3第三個參數…直到$9
$*???? 擴展所有的位置參數給命令
$@???? 擴展所有的位置參數給命令,但是當“$@”使用時,參數個別標注
?