天天看點

Linux--檔案搜尋

文章目錄

  • ​​一、locate--較簡單的方式查找檔案​​
  • ​​二、find--較複雜的方式查找檔案​​
  • ​​2.1、test選項​​
  • ​​2.2、action選項​​
  • ​​2.3、傳回到playground檔案夾​​
  • ​​2.4、option選項​​

一、locate–較簡單的方式查找檔案

​locate​

​​指令通過快速搜尋資料庫,以尋找路徑名與給定的子字元串相比對的檔案,同時輸出所有比對結果。例如,假定查找名稱以zip字元串開頭的程式,由于查找的是程式檔案,是以可以認為包含所要查找的程式的路徑名應以bin/結尾。

是以,可以嘗試下面的指令行。

[wangjichuan@mr-jarvis ~]$ locate      

​locate​

​程式将搜尋該路徑名資料庫,并輸出檔案名包含字元串bin/zip的所有檔案。

Linux--檔案搜尋

有時搜尋需求并不是這麼簡單,這時便可以用​

​locate​

​​指令結合其他諸如​

​grep​

​這樣的工具實作一些更有趣的搜尋。

Linux--檔案搜尋

​locate​

​​程式已經使用了很長時間,是以出現了多種衍生體。​

​slocate​

​​和​

​mlocate​

​​是現代Linux發行版本中最常見的兩個衍生體,而它們通常都是由名為locate的符号連結通路的。不同版本的​

​locate​

​​有一些相同的選項設定,而有些版本則包括正規表達式比對和通配符支援等。我們可以檢視​

​locate​

​​的​

​man​

​​手冊頁确定系統安裝的是哪個版本的​

​locate​

​。

二、find–較複雜的方式查找檔案

​locate​

​​程式查找檔案僅僅是依據檔案名,而​

​find​

​​程式則是依據檔案的各種屬性在既定的目錄(及其子目錄)裡查找。

​​

​find​

​​最簡單的用法就算使用者給定一個或是更多個目錄名作為其搜尋範圍。下面就用​

​find​

​指令列出目前系統主目錄(~)下的檔案清單清單。

[wangjichuan@mr-jarvis ~]$ find      

對于一些比較活躍的使用者,一般系統内檔案會比較多,使得上訴指令行輸出的清單肯定很長。不過,清單資訊是以标準形式輸出的,是以可以直接将此輸出結果作為其他程式的輸入。如下就是用​

​wc​

​​程式計算​

​find​

​指令搜尋到的檔案的總量。

Linux--檔案搜尋

​find​

​指令的美妙之處就是可以用來搜尋符合特定要求的檔案,它通過綜合應用test選項、action選項以及option選項實作進階檔案搜尋。

2.1、test選項

假定我們想要查找的是目錄檔案,我們可以添加下面的test選項達到此目的。

[wangjichuan@mr-jarvis ~]$ find ~  -type  d  |  wc      

添加test參數​

​-type d​

​​可以将搜尋範圍限制為目錄,而下面的例子中使用​

​-type f​

​則表示隻對普通檔案進行搜尋。

[wangjichuan@mr-jarvis ~]$ find ~  -type  f  |  wc      

find支援搜尋的檔案類型

檔案類型 描述
b 塊裝置檔案
c 字元裝置檔案
d 目錄
f 普通檔案
l 符号連結

另外我們還可以添加其他的test選項參數實作依據檔案大小和檔案名的搜尋。如下指令行就是用來查找所有符合*.JPG通配符格式以及大小超過1MB的普通檔案。

[wangjichuan@mr-jarvis ~]$ find ~  -type  f   -name  "*.JPG"  -size  +1M  |  wc      

本例中添加的​

​-name "*.JPG"​

​​的test選項表示查找的是符合.JPG通配符格式的檔案。注意,這裡将通配符擴在雙引号中是為了避免shell路徑名擴充。另外ia添加的​

​-size +1M​

​的test選項,前面的加号表示查找的檔案大小比給定的數值1M大。若字元串前面是減号則代表要比給定數值小,沒有符号則表示與給定值完全相等。為末的M是計量機關MB(兆位元組)的簡寫,下表列出了每個字母與特定計量機關之間的對應關系。

find支援的計量機關

字母 機關
b 512位元組的塊(沒有具體說明時的預設值)
c 位元組
w 兩個位元組的字
k KB(每機關包含1024位元組)
M MB(每機關包含1048576位元組)
G GB(每機關包含1073741824位元組)

​find​

​指令支援多種test參數,下表概括了一些常見的參數。

find指令的test參數

test參數 描述
-cmin n 比對n分鐘前改變狀态(内容或屬性)的檔案或目錄。如果不到n分鐘,就用-n,如果超過n分鐘,就用+n
-cnewer file 比對内容或屬性的修改時間比檔案file更晚的檔案或目錄
-ctime n 比對系統中n*24小時前檔案狀态被改變(内容、屬性、通路權限等)的檔案或目錄
-empty 比對空檔案及空目錄
-group name 比對屬于name組的檔案或目錄。name可以描述為組名,也可以描述為該組的ID号
-iname pattern 與-name test項功能類似隻是不區分大小寫
-inum n 比對索引節點是n的檔案,該test選項有助于查找某個特定索引節點上的所有硬體連接配接
-mmin n 比對n分鐘前内容被修改的檔案或目錄
-mtime n 比對n*24小時前隻有内容被更改的檔案或目錄
-name pattern 比對由特定通配符模式的檔案或目錄
-newer file 比對内容的修改時間比file檔案更近的檔案或目錄。這在編寫shell腳本進行檔案備份的時候非常有用。每次建立備份時,更新某個檔案(比如日志),然後用find+此參數選項來确定上一次更新後哪個檔案改變了
-nouser 比對不屬于有效使用者的檔案或目錄。該test可以用來查找那些屬于已删除賬戶的檔案,也可以用來檢測攻擊者的活動
-nogroup 比對不屬于有效組的檔案或目錄
-perm mode 尋找通路權限與既定模式比對的檔案或目錄。既定模式可以以八進制或符号的形似表示
-samefile name 與-inum test選項類似。比對與file檔案用相同的inode号的檔案
-size n 比對n大小的檔案
-type 比對c類型的檔案
-user name 比對屬于name使用者的檔案和目錄。name可以描述為使用者名也可以描述為該組的ID号
注意:前面所講述的“+”和“-”号的用法适用于所有用到數值參數的情況

操作符

即使擁有了​​

​find​

​​指令提供的所有test參數,我們仍然會需要一個更好的工具來描述test參數之間的邏輯關系。例如,如果我們需要确定某目錄下是否所有的檔案和子目錄都有安全的通路權限,該怎麼辦?原則上就是去查找那些通路權限不是0600的檔案和通路權限不是0700的子目錄。幸運的時,​

​find​

​​指令的test選項可以結合邏輯操作進而建立具有複雜邏輯關系的比對條件。我們可以用下面的指令行來滿足上述​

​find​

​指令的比對搜尋。

[wangjichuan@mr-jarvis ~]$ find ~  \( -type f -not -perm 0600 \) -or \(  -type d -not -perm 0700  \)      

find指令的邏輯操作符

操作符 功能描述
-and 查找使該操作符兩邊的檢驗條件都是i真的比對檔案。有時直接縮寫成-a。注意如果兩個檢測條件之間沒有顯示的顯示操作符,and就是預設的邏輯關系
-or 查找使該操作符任何一邊的檢測條件為真的比對檔案。有時直接縮寫成-o
-not 查找使該操作符後面的檢測條件為假的比對檔案。有時直接縮寫成-!
() 多個檢測條件和邏輯操作符一起組成更長的表達式,而()操作符就是用來區分邏輯表達式優先權的。預設的情況下,find指令從左向右運算邏輯值。然而有時為了獲得想要的結果必須擾亂預設的執行順序,即便不需要,将一串字元表達式擴起來對提高指令的可讀性也很有幫助。請注意,括号字元在shell環境中有特殊意義,是以必須将它們在指令行中用引号引起來,這樣此阿能作為find的參數傳遞,通常用反斜杠來避免這樣的問題

2.2、action選項

前面的​

​find​

​​指令已經查找到所需要的檔案,但是我們真正想做的是處理已查找到的檔案。幸運的是,​

​find​

​指令允許直接對搜尋結果執行動作。

預定義動作

對搜尋到的檔案進行操作,既可以用諸多現成的預定義動作指令,也可以使用使用者自定義的動作。首先來看一些預定義動作:

預定義的find指令操作

動作 功能描述
-delete 删除比對檔案
-ls 對比對檔案執行ls操作,以标準格式輸出其檔案名以及所要求的其他資訊
-print 将比對的檔案的全路徑以标準形式輸出。當沒有指定任何具體操作時,該操作是預設操作
-quit 一旦比對成功便退出

與test參數選項相比,actions參數選項數量更多,可以參考find的man手冊頁擷取更全面的資訊。

​​

​find ~​

​​,此指令産生了一個包含目前系統主(~)目錄中所有檔案和子目錄的清單。該清單之是以會在螢幕上顯示,是因為在沒有指定其他操作的情況下,-print操作是預設的。是以,​

​find ~​

​​與​

​find ~ -print​

​​是等效的。

當然也可以使用​​

​find​

​指令删除滿足特定條件的檔案。示例如下,此指令行用于删除.BAK(這種檔案一般是用來指定備份檔案的)字尾的檔案。

[wangjichuan@mr-jarvis ~]$ find   ~   -type   f    -name   '*.BAK'      

本例中,使用者主目錄及其子目錄下的每個檔案都被搜尋了一遍比對檔案名以.BAK結尾的檔案。一旦被找到,則直接删除。

注意:毫無疑問,使用-delete操作時一定要格外小心,最好先用-print操作确認搜尋結果後再執行-delete删除指令
[wangjichuan@mr-jarvis ~]$ find   ~   -type   f    -name   '*.BAK'      

上述指令用來查找所有檔案名以.BAK結尾的普通檔案(-type f)并且以标準形式(-print)輸出每個比對檔案的相關路徑名。然而,該指令行之是以照這樣的方式執行是由每個test選項和action選項之間的邏輯關系決定的。記住,每個test選項和action選項之間預設的邏輯關系是與(and)邏輯。下面的指令行邏輯關系能更清楚地展現這一點:

[wangjichuan@mr-jarvis ~]$ find   ~   -type   f    -name   '*.BAK'      

test選項與action選項之間邏輯關系決定了它們的執行情況,是以test選項和action選項的順序很重要。例如,如果重新排列這些test選項和action選項,并将​

​-print​

​操作作為邏輯運算的第一個操作數,那麼指令行的運作結果将會有很大的不同。

[wangjichuan@mr-jarvis ~]$ find   ~   -print   -type   f     -and    -name   '*.BAK'      

此指令行會把每個檔案顯示出來(因為-print操作運算符總是為真),然後在對檔案類型以及特定的檔案擴充名進行比對檢查。

使用者自定義操作

除了已有的預定義操作指令,同樣也可以任意調用使用者想要操作的操作指令。傳統的方法就是像以下指令行使用-exec操作。

-exec command {}      

該格式中的command表示要執行的操作指令名,{}花括号代表的是目前路徑,而分号作為必需的分隔符表示指令結束。使用​

​-exec​

​​完成​

​-delete​

​操作示例如下:

-exec  rm  '{}'  ';'      

同樣,由于括号和分号字元在shell環境下有特殊含義,是以在輸入指令行時,要将它們用引号引起來或者使用轉義符隔開。

當然,互動式地執行使用者自定義操作也不是不可能。通過使用-ok操作取代原來的​

​-exec​

​操作,每一次指定指令執行之前系統都會詢問使用者。

Linux--檔案搜尋

上例中,查找檔案名以b字元開始的檔案,并且每次找到比對檔案後執行​

​ls -l​

​​指令。​

​-ok​

​操作會在ls指令執行之前詢問使用者是否執行。

提高效率

當使用​

​-exec​

​操作時,每次查找到比對檔案後都會調用執行一次指定指令。但有時使用者更希望隻調用一次指令就完成對所有檔案的操作。例如,多數人可能更喜歡這樣的指令執行方式。

ls  -l  file1
ls      

而不是以下這樣的方式:

ls      

第一種方式隻需要執行指令一次,而第二種方式則要多次重複執行。實作這樣的一次操作有兩種方法:一種方式比較傳統,使用為外部指令​

​xargs​

​​;另一種則是使用​

​find​

​本身自帶的新特性。首先介紹下第二種方法。

find   ~   -type   f   -name   'foo*'   -exec   ls  -l   '{}'   ';'      

每次找到比對檔案後就執行一次​

​ls​

​指令。将上述指令行改為下面的指令行。

find   ~   -type   f   -name   'foo*'   -exec   ls  -l   '{}'      

我們也能得到相同的結果,但是系統整體隻執行一次​

​ls​

​指令

同樣我們可以使用​

​xargs​

​​指令獲得相同的效果,​

​xargs​

​​處理标準輸入資訊并将其轉變為某指定指令的輸入參數清單。結合前面的執行個體,我們可以這樣使用​

​xargs​

​指令。

find   ~   -type   f   -name   'foo*'   -print   |   xargs   ls      

該指令行中,find指令的執行結果直接作為​

​xargs​

​​輸入,xargs反過來将其轉換成了​

​ls​

​​指令的輸入參數清單,最後執行​

​ls​

​操作。

注意:雖然一個指令行中可允許輸入的參數有很多,但這并不表示可以無限輸入,也存在指令行過長而使得shell編輯器無法承受的情況。如果指令行中包含的輸入參數太多而超過了系統支援的最大長度,xargs隻會盡可能對最大數量的參數執行指定操作,并不斷重複這一過程直到所有标準輸入全部處理完畢。在xargs指令後面添加–show-limits選項,即可直到指令行最大能承受的參數數量。

2.3、傳回到playground檔案夾

現在可以實際應用 ​

​find​

​指令了。首先讓我們建立一個包含很多子目錄及檔案的playground檔案夾平台。

[wangjichuan@mr-jarvis ~]$ mkdir -p playground/dir-{00{1..9},0{10..99},100}
[wangjichuan@mr-jarvis ~]$ touch playground/dir-{00{1..9},0{10..99},100}/file-{A..Z}      

我們使用上述指令建立了一個包含100個子目錄的playground檔案夾,并且每個子目錄中又包含26個空檔案。

我們創造這個奇迹的方法包含了一個熟悉指令​

​mkdir​

​​、一個奇異的shell花括号擴充以及一個新指令​

​touch​

​​。​

​mkdir​

​指令結合-p選項(-p選項使mkdir指令按指定的路徑建立父目錄)的同時用花括号擴充,便完成了100個目錄的建立。

​touch​

​指令一般用于設定或是更新檔案的修改時間。然而,當檔案名參數是一個不存在的檔案時,那麼該指令就會建立一個空檔案。

playground檔案夾裡,總共建立了100個較多file-A的檔案。現在,我們可以查找它們。

Linux--檔案搜尋
注意:與​

​ls​

​​指令不同,​

​find​

​指令不會産生有排列順序的結果,其輸出順序是由在儲存設備中的布局決定的。

下面來看一個根據檔案的修改時間查找檔案的例子,這在建立備份檔案以及按時間順序排列檔案是非常有用。首先需要建立一個用作比較時間的參照檔案。

[wangjichuan@mr-jarvis ~]$ touch      

該指令行建立了一個名為timestamp的空檔案,并将目前時刻設為該檔案的修改時間。我們可以使用另外一個便捷的指令​

​stat​

​​來檢驗執行效果,​

​stat​

​​指令可以說是​

​ls​

​的增強版,該指令會将系統所掌握檔案的所有資訊及屬性全部顯示出來。

Linux--檔案搜尋

當我們再一次對此檔案執行​

​touch​

​​指令并用​

​stat​

​指令檢驗時,會發現檔案的時間得到了更新。

Linux--檔案搜尋

接下來,我們便可以使用​

​find​

​指令更新playground檔案夾裡的一些檔案。

[wangjichuan@mr-jarvis ~]$ find    plauground   -type   f   -name   'file-B'   -exec   touch   '{}'   ';'      

上述指令更新了playground檔案夾裡面叫做file-B的所有檔案。下面我們通過比較參照檔案timestamp與其他檔案的修改時間,使用​

​find​

​指令查找剛剛被更新的檔案。

[wangjichuan@mr-jarvis ~]$ find      

指令行的運作結果包含100個檔案名為file-B的檔案。由于我們是在對timestamp檔案執行了​

​touch​

​​指令之後,才對playground檔案夾和宗對名為file-B的所有檔案執行力touch操作,是以它們現在要比timestamp檔案新,進而我們可選用​

​-newer​

​ test選項來查找。

2.4、option選項

option選項用于控制​

​find​

​​指令的搜尋範圍。在構成​

​find​

​指令的表達式時,它們可能包含在其他測試選項或行為選項之中。下表列出了最常用的option選項:

find指令的option選項

選項 描述
-depth 引導find程式處理目錄前先處理目錄内檔案。當指定-delete操作時,該參數選項會自動調用
-maxdepth levels 當執行測試條件行為時,設定find程式陷入目錄數的最大級别數
-mindepth levels 當應用測試條件行為之前,設定find程式陷入目錄數的最小級别數
-mount 引導find不去周遊挂載在其他檔案系統上的目錄