在執行某個命令的時候,有時需要依賴於前一個命令是否執行成功。例如,假設你希望將一個目錄中的文件全部拷貝到另外一個目錄中後,然後刪除源目錄中的全部文件。在刪除
之前,你希望能夠確信拷貝成功,否則就有可能丟失所有的文件。
如果希望在成功地執行一個命令之後再執行另一個命令,或者在一個命令失敗後再執行另一個命令,&&和||可以完成這樣的功能。相應的命令可以是系統命令或shell腳本。Shell還提供了在當前shell或子shell中執行一組命令的方法,即使用()和{ }。
使用& &的一般形式為:
命令1 && 命令2
這種命令執行方式相當地直接。& &左邊的命令(命令1)返回真(即返回0,成功被執行)後,& &右邊的命令(命令2)才能夠被執行;換句話說,“如果這個命令執行成功& &那麼執行這個命令”。
$ mv /apps/bin /apps/dev/bin && rm -r /apps/bin
在上面的例子中,/apps/bin目錄將會被移到/apps/dev/bin目錄下,如果它沒有被成功執行,就不會刪除/apps/bin目錄。
在下面的例子中,文件quarterend.txt首先將被排序並輸出到文件quarter.sorted中,只有這一命令執行成功之後,文件quarter .sorted才會被打印出來:
$ sort quarter_end.txt > quarter.sorted && lp quarter.sorted
使用| |的一般形式為:
命令1 || 命令2
| |的作用有一些不同。如果| |左邊的命令(命令1)未執行成功,那麼就執行| |右邊的命令(命令2);或者換句話說,“如果這個命令執行失敗了|| 那麼就執行這個命令”。
[root@localhost huangcd]# cp gsdf.txt opps.txt || echo "if you are seeing this cp failed"
cp: 無法 stat “gsdf.txt”: 沒有那個文件或目錄
if you are seeing this cp failed
這裡有一個更為實用的例子。我希望從一個審計文件中抽取第1個和第5個域,並將其輸出到一個臨時文件中,如果這一操作未成功,我希望能夠收到一個相應郵件:
[root@localhost huangcd]# awk '{print $1,$5}' acc.qtr >qtr.tmp ||echo "sorry hte payroll extraction didn't work" |mail root
在這裡不只可以使用系統命令;這裡我們首先對monthend.txt文件執行了一個名為comet的shell腳本,如果該腳本未執行成功,該shell將結束。
$ comet month_end.txt || exit
用()和{ }將命令結合在一起:
如果希望把幾個命令合在一起執行, shell提供了兩種方法。既可以在當前shell也可以在子shell中執行一組命令。
為了在當前shell中執行一組命令,可以用命令分隔符隔開每一個命令,並把所有的命令用圓括號()括起來。
它的一般形式為:
(命令1;命令2;. . .)
如果使用{ }來代替(),那麼相應的命令將在子shell而不是當前shell中作為一個整體被執行,只有在{ }中所有命令的輸出作為一個整體被重定向時,其中的命令才被放到子shell中執行,否則在當前shell執行。它的一般形式為:
{命令1;命令2;. . . }
我很少單獨使用這兩種方法。我一般只和& &或| |一起使用這兩種方法。
再回到前面那個comet腳本的例子,如果這個腳本執行失敗了,我很可能會希望執行兩個以上的命令,而不只是一個命令。我可以使用這兩種方法。這是原先那個例子:
$ comet month_end.txt || exit
現在如果該腳本執行失敗了,我希望先給自己發個郵件,然後再退出,可以用下面的方法來實現:
[root@localhost huangcd]# eomet month_end.txt||(echo "hello,guess what!comet did not work"|mail root ; exit)
在上面的例子中,如果只使用了命令分隔符而沒有把它們組合在一起, shell將直接執行
最後一個命令(exit)。
我們再回頭來看看前面那個使用& &排序的例子,下面是原來的那個例子:
$ sort quarter_end.txt > quarter.sorted && lp quarter.sorted
使用命令組合的方法,如果sort命令執行成功了,可以先將輸出文件拷貝到一個日志區,然後再打印。