linux學(xué)習(xí) 2009-01-13 16:44:50 閱讀30 評(píng)論0 字號(hào):大中小 訂閱
我們從一個(gè)Shell腳本的內(nèi)部執(zhí)行兩種類型的命令。也就是通常(normal)的命令,這樣的命令我們也可以在命令行的方式下來(lái)運(yùn)行,稱為處部命令,另 一種就是我們前面所說(shuō)的內(nèi)建(built-in)命令,稱之為內(nèi)部命令。內(nèi)建命令是在Shell的內(nèi)部來(lái)實(shí)現(xiàn)的而不能為外部程序所調(diào)用。然而大多數(shù)的內(nèi)部 命令也會(huì)作為相對(duì)獨(dú)立的單一程序來(lái)提供,而這也是POSIX 標(biāo)準(zhǔn)所要求的一部分。通常來(lái)說(shuō)內(nèi)部命令與外部命令并沒(méi)有太大的區(qū)別,除非是這個(gè)內(nèi)部運(yùn)行得更為高效。
然而在這里我們只會(huì)討論一些主要的命令,包括我們編寫(xiě)一下腳本時(shí)所需要用到的外部與內(nèi)部命令。作為一個(gè)Linux用戶我們會(huì)知道一些其他的可以在命令行來(lái)運(yùn)行的命令。我們應(yīng)該記住除了我們?cè)谶@里所提到一些內(nèi)建命令以后我們還可以在腳本中使用我們所知道的一些其他的命令。
break
當(dāng)我們要從一個(gè)for,while或是until循環(huán)中退出時(shí)我們可以使用這個(gè)命令。我們也可以傳遞給break另外一個(gè)數(shù)字參數(shù),而這個(gè)數(shù)字參數(shù)正是我 們要退出的循環(huán)次數(shù)。因?yàn)檫@樣會(huì)使得我們的腳本變得難于閱讀,所以我們并不推薦大家來(lái)使用這樣的方式。在默認(rèn)的情況下,break只會(huì)退出單一的層次。如 下面的例子:
#!/bin/sh
rm -rf fred*
echo > fred1
echo > fred2
mkdir fred3
echo > fred4
for file in fred*
do
if [ -d “$file” ]; then
break;
fi
done
echo first directory starting fred was $file
rm -rf fred*
exit 0
:命令
冒號(hào)命令只是一個(gè)空命令。這個(gè)命令用來(lái)作為true的別名而簡(jiǎn)化邏輯條件是相當(dāng)有用的。因?yàn)樗且粋€(gè)內(nèi)建的命令,所以他運(yùn)行得要比true快速,然而他的輸出卻并不是易于理解的。
我們可以看到在while循環(huán)中使用這個(gè)命令。while :可以替代更為常見(jiàn)的while true來(lái)實(shí)現(xiàn)無(wú)限的循環(huán)。
:結(jié)構(gòu)在變量的設(shè)置條件中也是相當(dāng)有用的,例如:
: ${var:=value}
如果沒(méi)有:,shell會(huì)試著將$var作為一個(gè)命令來(lái)對(duì)待。
#!/bin/sh
rm -f fred
if [ -f fred ]; then
:
else
echo file fred did not exist
fi
exit 0
continue
與C語(yǔ)言相類似,這個(gè)命令可以使得for,while,until中的變量使用列表中的下一個(gè)值繼續(xù)執(zhí)行下一次循環(huán)。
#!/bin/sh
rm -rf fred*
echo > fred1
echo > fred2
mkdir fred3
echo > fred4
for file in fred*
do
if [ -d “$file” ]; then
echo “skipping directory $file”
continue
fi
echo file is $file
done
rm -rf fred*
exit 0
continue命令后可以跟一個(gè)用來(lái)作為一個(gè)可選參數(shù)的數(shù)字,這樣我們就可以部分的跳出嵌套循環(huán)。然而這樣的參數(shù)并不常用,因?yàn)檫@樣會(huì)使得我們的腳本難于理解。例如:
for x in 1 2 3
do
echo before $x
continue 1
echo after $x
done
這個(gè)腳本的輸出結(jié)果如下:
before 1
before 2
before 3
。命令
。命令會(huì)在當(dāng)前的Shell中執(zhí)行命令:
。 。/shell_script
通常情況下,當(dāng)一個(gè)腳本執(zhí)行一個(gè)外部的命令或是腳本時(shí),就會(huì)創(chuàng)建一個(gè)新的循環(huán)或是子Shell,這個(gè)外部命令會(huì)在新的環(huán)境下運(yùn)行,然而這個(gè)新的環(huán)境就會(huì)無(wú)視返回給父Shell的返回代碼。但是外部的資源和。命令使得被調(diào)用腳本中所列出的命令在同一個(gè)環(huán)境下來(lái)運(yùn)行。
這樣就意味著在通常的情況下命令對(duì)環(huán)境變量所做的修改會(huì)丟失。而另一方面,。命令可以允許被執(zhí)行的命令改變當(dāng)前的運(yùn)行循環(huán)。當(dāng)我們要使用一個(gè)腳本作為包裝 來(lái)為后來(lái)一些其他命令的運(yùn)行設(shè)置環(huán)境時(shí)是相當(dāng)有用的。例如:如果我們同時(shí)在幾個(gè)不同的工程上進(jìn)行工作,有時(shí)我們就會(huì)發(fā)現(xiàn)我們需要使用一個(gè)不同的參數(shù)來(lái)調(diào)用 命令,也許是調(diào)用一個(gè)老版本的編譯器來(lái)維護(hù)一個(gè)古老的程序。
在Shell腳本中,。(dot)命令的工作方式與C或是C++中的#include的工作方式相類似。雖然他并不真正包含一個(gè)腳本,但是他確實(shí)是在當(dāng)前的條件下運(yùn)行命令,所以我們可以使用這個(gè)命令在一個(gè)腳本中進(jìn)行變量或是函數(shù)定義的合并。
在下面的這個(gè)例子中,我們?cè)诿钚械姆绞较率褂胐ot命令,但是我們也可以在一個(gè)腳本中使用這個(gè)命令。
1 假設(shè)我們有兩個(gè)文件,而這兩個(gè)文件所包含是為兩個(gè)不同的開(kāi)發(fā)環(huán)境所做的環(huán)境設(shè)置。要為古老的,經(jīng)典的命令設(shè)置環(huán)境,classic_set,我們可以使用下面的命令:
#!/bin/sh
version=classic
PATH=/usr/local/old_bin:/usr/bin:/bin:.
PS1=”classic> “
2而對(duì)于新的命令我們使用latest_set:
#!/bin/sh
version=latest
PATH=/usr/local/new_bin:/usr/bin:/bin:.
PS1=” latest version> “
我們可以使用dot命令將這些腳本進(jìn)行合并來(lái)設(shè)置環(huán)境,如下面的操作:
$ . ./classic_set
classic> echo $version
classic
classic> . latest_set
latest version> echo $version
latest
latest version>
echo
僅管在現(xiàn)代的Shell中使用printf命令,但是在這里我們?nèi)匀蛔裱ǔ5牧?xí)慣來(lái)使用echo命令后跟新行字符的字符串。
一個(gè)通常的問(wèn)題就是如何來(lái)禁止一個(gè)新行字符。不幸的,不同版本的Unix實(shí)現(xiàn)了不同的解決方法。在Linux中通用的作法是:
echo -n “string to output”
但是也許我們常會(huì)看到下面的情況:
echo -e “string to output\c”
在第二種方法,echo -e確保允許解釋一些轉(zhuǎn)義字符,例如新\t解釋為tab,而將\n解釋為回車換行。這在通常的情況下是默認(rèn)的設(shè)置
eval
eval命令允許我們進(jìn)行參數(shù)的賦值。他是Shell的內(nèi)建命令而并不作為一個(gè)單獨(dú)的命令而存在。下面一個(gè)從X/Open所借用來(lái)的簡(jiǎn)短的例子可以很好的說(shuō)明這個(gè)問(wèn)題。
foo=10
x=foo
y=’$’$x
echo $y
這個(gè)例子的輸出結(jié)果為$foo,然而如果我們用下面的例子:
foo=10
x=foo
eval y=’$’$x
echo $y
這樣的輸出結(jié)果就為10.這樣eval就有一些像另外的一個(gè)$:他會(huì)提供給我們一個(gè)變量的值。
eval命令是非常有用的,他會(huì)允許我們隨時(shí)創(chuàng)建和運(yùn)行代碼。他確實(shí)會(huì)將腳本的高度復(fù)雜化,但是他卻會(huì)允許我們做一些平常來(lái)說(shuō)非常困難甚到是不可能的事情。
exec
exec命令有兩種不同的用法。他最通常的用法是用一個(gè)不同的程序來(lái)替換當(dāng)前的Shell。例如;
exec wall “Thanks for all the fish”
在腳本中會(huì)使用wall命令來(lái)替換當(dāng)前的Shell。在exec命令之后的腳本內(nèi)容不會(huì)處理,因?yàn)閳?zhí)行這個(gè)腳本的Shell已經(jīng)不存在了。
exec的第二種用法就是用來(lái)修改當(dāng)前文件的描述符:
exec 3< afile
這個(gè)結(jié)果是是為了從文件afile文件中讀入內(nèi)容而打開(kāi)文件描述符3.這樣有用法并不常見(jiàn)。
exit n
exit命令會(huì)使得腳本返回返回代碼。如果我們是在交互的Shell中運(yùn)行這個(gè)命令,他就會(huì)使得我們退出會(huì)話。如果我們不指定我們的腳本不指定返回狀態(tài)而退出,那么腳本中上一次命令的執(zhí)行結(jié)果就會(huì)作為返回值。通常指定返回值是一個(gè)很好的做法。
在Shell編程中,返回代碼0為成功,1到125是錯(cuò)誤代碼,這些錯(cuò)誤代碼可以為腳本所使用。保留的值具有保留的含義:
126 文件是不可執(zhí)行的
127 命令沒(méi)有找到
128及以上 發(fā)生信號(hào)
使用0作為成功代碼在許多的C或是C++程序員看來(lái)會(huì)有一些的不同。這最大的優(yōu)點(diǎn)就是在腳本中允許我們使用125種用戶定義的錯(cuò)誤代碼而不需要全局錯(cuò)誤代碼變量。
在下面這個(gè)例子中,如果在當(dāng)前的目錄下存在。profile文件就回成功值。
#!/bin/sh
if [ -f .profile ]; then
exit 0
fi
exit 1
如果我們是一個(gè)甘受懲罰的人或者是需要簡(jiǎn)潔的腳本,我們可以用我們?cè)谇懊嬉?jiàn)過(guò)的AND和OR列表來(lái)重寫(xiě)我們的腳本,而將所有的內(nèi)容放在一行:
[ -f .profile ] && exit 0 || exit 1
export
export命令可以使得變量以其子Shell中的參數(shù)進(jìn)行命令.在默認(rèn)的情效況下,在一個(gè)Shell中所創(chuàng)建的變量在另一個(gè)所調(diào)用的Shell中并不是 可見(jiàn)的.export命令可以由他的參數(shù)創(chuàng)建一個(gè)環(huán)境變量,這個(gè)變量可以為當(dāng)前程序中所調(diào)用的其他的腳本或是程序可見(jiàn).更為技術(shù)的一點(diǎn)來(lái)說(shuō),由任何子進(jìn)程 序所引進(jìn)的環(huán)境變量是由這個(gè)Shell派生的.這個(gè)命令的含義以及用法可以從下面的兩個(gè)腳本export1和export2來(lái)很好的進(jìn)行演示.
我們先列出export2的腳本內(nèi)容:
#!/bin/sh
echo “$foo”
echo “$bar”
下面的是export1中的內(nèi)容,在這個(gè)腳本的結(jié)尾處我們調(diào)用export2:
#!/bin/sh
foo=”The first meta-syntactic variable”
export bar=”The second meta-syntactic variable”
export2
如果我們運(yùn)行這個(gè)腳本我們可以得到下面的結(jié)果:
$ export1
The second meta-syntactic variable
$
之所以發(fā)生第一行的空行是因?yàn)樵趀xport2中變量foo并不是可見(jiàn)的,所以$foo被賦值為空值,輸出一個(gè)空的變量就會(huì)得到一個(gè)新行.
一旦一個(gè)變量由一個(gè)Shell引入,那么他在由這個(gè)Shell中所派生的或是在這個(gè)Shell中所依次調(diào)用的腳本中都是可見(jiàn)的.如果腳本export2調(diào)用了另一個(gè)腳本,那么對(duì)于另一個(gè)腳本來(lái)說(shuō)這個(gè)變量的值仍然是可見(jiàn)的.
命令set -a或是set -allexport可以引入所有的變量.
expr
expr命令會(huì)將他的參數(shù)作為一個(gè)表達(dá)式來(lái)對(duì)待.他最常見(jiàn)的用法是用在如下面形式的簡(jiǎn)單算術(shù)中:
x=`expr $x + 1`
在這里的反引號(hào)(`)是將命令expr $x+1的結(jié)果作為變量x的值.我們也可以用語(yǔ)法$()來(lái)寫(xiě)這個(gè)句子而不使用反引號(hào)的形式,如下面的形式:
x=$(expr $x + 1)
expr命令是一個(gè)相當(dāng)強(qiáng)大的命令,他可以處理許多表達(dá)賦值的問(wèn)題.他的一些原則如下表所示:
expr1 | expr2 如果expr1不為空則為expr1,否則為expr2
expr1 & expr2 如果expr2或是expr1為零則為零,否則為expr1
expr1 = expr2 相等
expr1 > expr2 大于
expr1 >= expr2 大于等于
expr1 < expr2 小于
expr1 <= expr2 小于等于
expr1 != expr2 不等于
expr1 + expr2 相加
expr1 - expr2 相減
expr1 * expr2 相乘
expr1 / expr2 整數(shù)相除
expr1 % expr2 整數(shù)取模
printf
printf命令只在現(xiàn)代的Shell中可用.X/Open建議我們最好應(yīng)使用echo來(lái)產(chǎn)生格式化的輸出.
語(yǔ)法格式如下:
printf “format string” parameter1 parameter2 ...
字符串的格式與我們?cè)贑或是C++中所見(jiàn)到的相類假,只是有一些限制.主要的區(qū)別在于Shell并支持浮點(diǎn)數(shù),因?yàn)镾hell中的所有算術(shù)運(yùn)算都是作為整 數(shù)來(lái)處理的.格式化字符串可以由字母,轉(zhuǎn)義序列和轉(zhuǎn)義符的任何組合來(lái)構(gòu)成.在格式化字符串中除了%和\的所有字符都可以進(jìn)行精確的輸出.
下面列出的是可以支持的轉(zhuǎn)義序列:
\\ 反斜線
\a 警告
\b 退格
\f 形成輸入字符
\n 新行字符
\r 回車
\t Tab字符
\v 垂直Tab
\ooo 由八進(jìn)制表示的單個(gè)字符
轉(zhuǎn)義字符是相當(dāng)復(fù)雜的,所以我們?cè)谶@里只是列出一些我們會(huì)常用到的內(nèi)容.更為詳細(xì)的內(nèi)容可以在在線的bash手冊(cè)中得到.轉(zhuǎn)義字符是%和緊跟其后的要轉(zhuǎn)義的字符組成的.下面列出一些主要的轉(zhuǎn)義字符:
d 輸出十進(jìn)制數(shù)
c 輸出一個(gè)字符
s 輸出一個(gè)字符串
% 輸出%字符
然后我們會(huì)使用格式化字符串來(lái)解釋其余的參數(shù)并進(jìn)行結(jié)果的輸出.例如:
$ printf “%s\n” hello
hello
$ printf “%s %d\t%s” “Hi There” 15 people
Hi There 15 people
在這里我們要注意我們必須使用""來(lái)使得Hi There字符串成為一個(gè)單一的參數(shù).
return
return命令會(huì)使得一個(gè)函數(shù)返回.我們?cè)谇懊娴囊恍┖瘮?shù)的用法中已經(jīng)注意到了這一點(diǎn).return命令會(huì)返回一個(gè)單一的數(shù)字參數(shù),而這個(gè)數(shù)字參數(shù)在調(diào)用這個(gè)函數(shù)的腳本中是可見(jiàn)的.如果沒(méi)有指定返回參數(shù),return在默認(rèn)情況下會(huì)返回上一次命令的返回代碼.
set
set命令會(huì)為Shell設(shè)置參數(shù)變量.這對(duì)于在輸出由空格區(qū)分的命令中使用域是很有用的一個(gè)方法.
假如我們要在我們的Shell腳本中使用當(dāng)前月份的名字.系統(tǒng)提供了一個(gè)日期的命令,這個(gè)命令含有字符串形式的月份,但是我們需要將他與其他的區(qū)域進(jìn)行分 離.我們可以使用set命令和$(...)結(jié)構(gòu)的組合來(lái)執(zhí)行日期命令并返回結(jié)果.日期命令的輸出是將月份的字符串作為他的第二個(gè)參數(shù).
如下面的例子:
#!/bin/sh
echo the date is $(date)
set $(date)
echo The month is $2
exit 0
這個(gè)程序?yàn)閐ate命令的輸出設(shè)置了參數(shù)列表,并且使用第二個(gè)參數(shù)$2來(lái)得到月份的名字.
在這里我們要注意的是我們使用date命令來(lái)作為一個(gè)簡(jiǎn)單的例子來(lái)展示如何解開(kāi)位置參數(shù).因?yàn)閐ate命令是與語(yǔ)言設(shè)置有關(guān)的,而事實(shí)上我們可以使用命令date +%B來(lái)得到月份的名字.date還有許多其他的格式選項(xiàng),我們可以從他的手冊(cè)頁(yè)中得到更為詳細(xì)的說(shuō)明.
我們還可以使用set命令來(lái)控制通過(guò)傳遞Shell參數(shù)的Shell執(zhí)行方式.這最通常的用法是使用命令set -x,這樣就會(huì)使得一個(gè)腳本顯示他當(dāng)前執(zhí)行命令的軌跡.
shift
shift命令可以使得所有的參數(shù)變量值減1,這樣$2就會(huì)變?yōu)?1,而$3就會(huì)變?yōu)?2,依次類推.這樣以后$1的值就會(huì)丟棄,而$0的值會(huì)保持不變. 如果在調(diào)用shift命令時(shí)指定了一個(gè)數(shù)字參數(shù),那么這些參數(shù)也會(huì)移動(dòng)一些相應(yīng)的位置.而其他的一些變量,$*,$@,$#也會(huì)為新的參數(shù)變量的范圍進(jìn)行 相應(yīng)的修改.
shift命令在參數(shù)之中進(jìn)行掃描是相當(dāng)有用的,如果我們的腳本需要10個(gè)或是更多的參數(shù),那么我們就需要使用shift來(lái)訪問(wèn)10個(gè)或是更多的內(nèi)容.
作為例子,我們可以像下面的形式來(lái)掃描所有的位置參數(shù):
#!/bin/sh
while [ “$1” != “” ]; do
echo “$1”
shift
done
exit 0
trap
trap命令可以用來(lái)指定在收到信號(hào)時(shí)所要進(jìn)行的動(dòng)作.一個(gè)常見(jiàn)的用法是在一個(gè)腳本被中斷時(shí)所做的處理工作.由于歷史的原因,Shell總是使用數(shù)字來(lái)代 表信號(hào),但是新的腳本可以通過(guò)#include signal.h并且忽略SIG前綴來(lái)使用信號(hào)的名字.如果我們要查看信號(hào)的數(shù)字和其相關(guān)的名字我們可以在命令提示下輸入trap -l命令.
trap命令可以通過(guò)緊跟信號(hào)的名字的方式來(lái)傳遞將要進(jìn)行的動(dòng)作:
trap command signal
我們要記住通常情況下腳本是從上到下進(jìn)行解釋的,我們必須在我們要保護(hù)的腳本部分之前來(lái)指定trap命令.
要將一個(gè)trap的條件設(shè)置為默認(rèn)的情況,我們可以簡(jiǎn)單的將命令指定為-.要忽略一個(gè)信號(hào),我們可以將命令設(shè)為空串``.一個(gè)沒(méi)有任何參數(shù)的trap命令會(huì)打印出當(dāng)前的動(dòng)作列表.
下面的表格列出了一些比較重要的標(biāo)準(zhǔn)的X/Open信號(hào),這些信號(hào)都可以被捕獲.更為詳細(xì)的內(nèi)容我們可以從信號(hào)手冊(cè)中得到.
HUP(1) 掛起.通常是當(dāng)一個(gè)終端離線或是用戶退出時(shí)發(fā)出.
INT(2) 中斷.通常是通過(guò)按下Ctrl+C發(fā)出的.
QUIT(3) 退出,通常是由Ctrl+\發(fā)出的.
ABRT(6) 中止,通常是由一些嚴(yán)重的運(yùn)行錯(cuò)誤發(fā)出的.
ALRM(14) 警告.通常是由處理超時(shí)發(fā)出的.
TERM(15) 結(jié)束.通常是當(dāng)系統(tǒng)關(guān)機(jī)時(shí)發(fā)出的.
下面的腳本模擬了一些簡(jiǎn)單信號(hào)的處理:
#!/bin/sh
trap ‘rm -f /tmp/my_tmp_file_$$’ INT
echo creating file /tmp/my_tmp_file_$$
date > /tmp/my_tmp_file_$$
echo “press interrupt (CTRL-C) to interrupt ....”
while [ -f /tmp/my_tmp_file_$$ ]; do
echo File exists
sleep 1
done
echo The file no longer exists
trap INT
echo creating file /tmp/my_tmp_file_$$
date > /tmp/my_tmp_file_$$
echo “press interrupt (control-C) to interrupt ....”
while [ -f /tmp/my_tmp_file_$$ ]; do
echo File exists
sleep 1
done
echo we never get here
exit 0
如果我們運(yùn)行這個(gè)命令,我們?cè)诿恳粋€(gè)循環(huán)中按下Ctrl+C,我們就會(huì)得到下面的輸出:
creating file /tmp/my_tmp_file_141
press interrupt (CTRL-C) to interrupt ....
File exists
File exists
File exists
File exists
The file no longer exists
creating file /tmp/my_tmp_file_141
press interrupt (CTRL-C) to interrupt ....
File exists
File exists
File exists
File exists
工作原理:
這個(gè)腳本使用trap命令來(lái)為命令rm -f /tmp/my_tmp_file_$$執(zhí)行時(shí)接收到INT信號(hào)時(shí)安排將會(huì)執(zhí)行的動(dòng)作.然后這個(gè)腳本會(huì)進(jìn)入一個(gè)循環(huán)直到文件存在.當(dāng)用戶按下Ctrl+C 時(shí),語(yǔ)句rm -f /tmp/my_tmp_file_$$被執(zhí)行,然后這個(gè)循環(huán)會(huì)重新開(kāi)始.因?yàn)檫@個(gè)文件已經(jīng)被刪除了,所以第一個(gè)while循環(huán)會(huì)正常的結(jié)束.
這個(gè)腳本然后會(huì)再一次使用trap命令,這一次是要指定當(dāng)INT信號(hào)發(fā)生時(shí)沒(méi)有命令被執(zhí)行.他會(huì)重新創(chuàng)建這個(gè)文件并進(jìn)入第二個(gè)循環(huán)語(yǔ)句.如果用戶在這時(shí)按 下Ctrl+C時(shí),沒(méi)有配置要執(zhí)行的語(yǔ)句,所以會(huì)發(fā)生默認(rèn)的動(dòng)作,即立即終止腳本.因?yàn)檫@個(gè)腳本是立即被終止的,所以最后的echo和exit命令并不會(huì) 執(zhí)行.
unset
unset命令會(huì)從當(dāng)前的環(huán)境中移除變量或是函數(shù).但是對(duì)于Shell自己定義的只讀的變量(例如IFS)不可以進(jìn)行這樣的操作.這個(gè)命令并不是經(jīng)常使用.
例如下面的這個(gè)例子:
#!/bin/sh
foo=”Hello World”
echo $foo
unset foo
echo $foo
兩個(gè)更為有用的命令和正則表達(dá)式
在我們開(kāi)始學(xué)習(xí)新的Shell編程知識(shí)之前,我們先來(lái)看一下兩個(gè)更為有用的兩個(gè)命令,這兩個(gè)命令雖然并不是Shell的一部分,但是在進(jìn)行Shell編程時(shí)卻會(huì)經(jīng)常用到.隨后我們會(huì)來(lái)看一下正則表達(dá)式.
find命令
我們先來(lái)看的是find命令.這個(gè)命令對(duì)于我們用來(lái)查找文件時(shí)是相當(dāng)有用的,但是對(duì)于Linux新手來(lái)說(shuō)卻有一些難于使用,在一定程序是由于他所帶的選項(xiàng),測(cè)試,動(dòng)作類型參數(shù),而且一個(gè)參數(shù)的執(zhí)行結(jié)果會(huì)影響接下來(lái)的參數(shù).
在我們深入這些選項(xiàng)和參數(shù)之前,我們先來(lái)看一個(gè)非常簡(jiǎn)單的例子.假如在我們的機(jī)子上有一個(gè)文件wish.我們來(lái)進(jìn)行這個(gè)操作時(shí)要以root身份來(lái)運(yùn)行,這樣就可以保證我們可以搜索整個(gè)機(jī)子:
# find / -name wish -print
/usr/bin/wish
#
正如我們可以想到的,他會(huì)打印出搜索到的結(jié)果.很簡(jiǎn)單,是不是?
然而,他卻需要一定的時(shí)間來(lái)運(yùn)行,因?yàn)樗矔?huì)同時(shí)搜索網(wǎng)絡(luò)上的Window機(jī)器上的磁盤(pán).Linux機(jī)器會(huì)掛載大塊的Window機(jī)器的文件系統(tǒng).他也會(huì)同時(shí)那些位置,雖然我們知道我們要查找的文件位于Linux機(jī)器上.
這也正是第一個(gè)選項(xiàng)的用武之地.如果我們指定了-mount選項(xiàng),我們就可以告訴find命令不要搜索掛載的目錄.
# find / -mount -name wish -print
/usr/bin/wish
#
這樣我們?nèi)匀豢梢运阉鬟@個(gè)文件,但是這一次并沒(méi)有搜索掛載的文件系統(tǒng).
find命令的完整語(yǔ)法如下:
find [path] [options] [tests] [actions]
path是一個(gè)很簡(jiǎn)單的部分:我們可以使用絕對(duì)路徑,例如/bin,或者是使用相對(duì)路徑,例如.. .如果我們需要我們還可以指定多個(gè)路徑,例如 find /var /home
主要的一些選項(xiàng)如下:
-depth 在查看目錄本身以前要先搜索目錄中的內(nèi)容
-follow 跟隨符號(hào)鏈接
-maxdepths N 在搜索一個(gè)目錄時(shí)至多搜索N層
-mount(或-xdev) 不要搜索其他的文件系統(tǒng)
下面的是一些test的選項(xiàng).我們可以為find命令指定大量的測(cè)試,并且每一個(gè)測(cè)試會(huì)返回真或是假.當(dāng)find命令工作時(shí),他會(huì)考查順序查找到的文件, 并且會(huì)在這個(gè)文件上按順序進(jìn)行他們所定義的測(cè)試.如果一個(gè)測(cè)試返回假,find命令會(huì)停止他當(dāng)前正在考查的文件并繼續(xù)進(jìn)行下面的動(dòng)作.我們?cè)谙卤碇辛谐龅?只是一些我們最常用到的測(cè)試,我們可以通過(guò)查看手冊(cè)頁(yè)得到我們可以利用find命令使用的可能的擴(kuò)展列表項(xiàng).
-atime N N天以前訪問(wèn)的文件
-mtime N N天以前修改的文件
-name pattern 除了路徑,與指定的類型匹配的文件名.為了保證指定的類型傳遞給find命令而并不是立即被Shell賦值,指定的類型必須用引號(hào)進(jìn)行引用.
-newer otherfile 與otherfile文件相比要新的文件
-type C C類型的文件,而這里的C可以指定的一種類型.最常用的是d代表目錄,而f是指普通的文件.對(duì)于其他的文件類型,我們可以查看手冊(cè)頁(yè).
-user username 指定的用戶所擁有的文件
我們也可以使用運(yùn)算符進(jìn)行測(cè)試的組合.大多數(shù)的有兩種格式:短格式和長(zhǎng)格式.
! -not 測(cè)試的反
-a -and 所有的測(cè)試必須為真
-o -or 測(cè)試中某一個(gè)為真
我們可以使用括號(hào)來(lái)強(qiáng)行改變測(cè)試和運(yùn)算符的次序.因?yàn)檫@些對(duì)于Shell來(lái)說(shuō)有著特殊的意義,所以我們也需要使用反斜線將他們作為一個(gè)整體進(jìn)行引用.另 外,如果我們?yōu)槲募付似ヅ漕愋?我們也必須用引號(hào)進(jìn)行引用,這樣就可以避免他們被Shell進(jìn)行擴(kuò)展,從而可以將他們直接傳遞給find命令.所以 如果我們要寫(xiě)一個(gè)這樣的測(cè)試,要查找比X文件要近或者是以一個(gè)范圍開(kāi)頭的文件,我們要寫(xiě)成下面的形式:
\(-newer X -o -name “_*” \)
現(xiàn)在我們要試著在當(dāng)前的目錄下查找最近修改日期比while2更近的文件,我們可以用下面的命令:
$ find . -newer while2 -print
.
./elif3
./words.txt
./words2.txt
./_trap
$
我們?cè)谏厦嫠玫拿羁雌饋?lái)似乎不錯(cuò),但是我們卻同時(shí)也搜索了當(dāng)前的目錄文件,而這并不是我們所希望的,我們所感興趣只是常規(guī)文件.所以我們可以加上另外一個(gè)測(cè)試-type f:
$ find . -newer while2 -type f -print
./elif3
./words.txt
./words2.txt
./_trap
$
工作原理:
這些命令是如何進(jìn)行工作的呢?我們指定find命令應(yīng)該在當(dāng)前的目錄下進(jìn)行查找(.),而我們所要查找的是比while2更新的文件(-newer while2),而且如果已經(jīng)傳遞了測(cè)試,還要測(cè)試這個(gè)文件是否為一個(gè)常規(guī)文件(-type -f).最后,我們使用我們以前用過(guò)的動(dòng)作,-print,僅僅是來(lái)驗(yàn)證我們所找到的文件.
下面我們要查找的文件或者是以下劃線開(kāi)頭的或者是要比while2文件新的文件,但是也必須為一個(gè)常規(guī)文件.這個(gè)例子可以向我們展示如何來(lái)進(jìn)行測(cè)試的組合:
$ find . \( -name “_*” -or -newer while2 \) -type f -print
./elif3
./words.txt
./words2.txt
./_break
./_if
./_set
./_shift
./_trap
./_unset
./_until
聯(lián)系客服