搜尋指令 which, whereis, locate, find的差別

由 Derek 發表於 五月 10, 2011 / 1 則評論

簡單的比較說明:

which 通常都是用來尋找『執行檔』

whereis 通常是用來尋找『特定檔案』

 

whersis】和【locate】搜尋時是以資料庫檔案裡的資料為主

find】搜尋時是以整個硬碟裡的資料為主

 

Linux下,find這個指令不常用到,因為不僅速度慢也很操硬碟。所以通常都是先使用whereis或是locate來檢查,最後真的找不到的話,才會使用到find來搜尋。

Whereislocate是利用資料庫來搜尋資料,並非實際搜尋硬碟。因此在找資料上的速度相當快速,也較省時間。

 

以下是各指令的說明

 

which 

這個指令是根據『PATH』這個環境變數所規範的路徑,去搜尋『執行檔』的檔名,而且which後面接的是『完整檔名』。若加上 -a 選項,則可以列出所有的可以找到的同名執行檔,而非僅顯示第一個!

 

[root@www ~]# which [-a] command

選項或參數:

-a :將所有由 PATH 目錄中可以找到的指令均列出,而不止第一個被找到的指令名稱

範例一:分別用root與一般帳號搜尋 ifconfig 這個指令的完整檔名

[root@www ~]# which ifconfig

/sbin/ifconfig            <== root 可以找到正確的執行檔名喔!

[root@www ~]# su – derek <==切換身份成為 derek 去!

[derek@www ~]$ which ifconfig

/usr/bin/which: no ifconfig in (/usr/kerberos/bin:/usr/local/bin:/bin:/usr/bin

:/home/derek/bin)         <==竟然一般身份帳號找不到!

# 因為 which 是根據使用者所設定的 PATH 變數內的目錄去搜尋可執行檔的!

# 不同的 PATH 設定內容所找到的指令當然不一樣啦!因為 /sbin 不在 derek 

# PATH 中,找不到也是理所當然的啊!瞭乎?

  

 

whereis

為什麼whereis的搜尋速度會比find快這麼多呢?

因為Linux 會將系統內所有的檔案都記錄在一個資料庫檔案裡面,當要使用whereislocate時,就會先以此資料庫檔案的內容為準。有時在使用這兩個執行檔的時後,會找到已經被殺掉的檔案。也有時後會找不到剛剛所建立的最新檔案,因為還沒有被記錄到此資料庫檔案中。

 

[root@www ~]# whereis [-bmsu] 檔案或目錄名

選項與參數:

-b    :只找可執行檔( binary )格式的檔案

-m    :只找在說明檔 manual 路徑下的檔案

-s    :只找 source 來源檔案

-u    :搜尋不在上述三個項目當中的其他特殊檔案

如果不加任何選項的話,那麼就將所有的資料列出來囉!

 

範例一:請用不同的身份找出 ifconfig 這個檔名

[root@www ~]# whereis ifconfig

ifconfig: /sbin/ifconfig /usr/share/man/man8/ifconfig.8.gz

[root@www ~]# su – derek        <==切換身份成為 derek

[derek@www ~]$ whereis ifconfig <==找到同樣的結果喔!

ifconfig: /sbin/ifconfig /usr/share/man/man8/ifconfig.8.gz

[derek@www ~]$ exit              <==回歸身份成為 root 去!

# 注意看,明明 which 一般使用者找不到的 ifconfig 卻可以讓 whereis 找到!

# 這是因為系統真的有 ifconfig 這個『檔案』,但是使用者的 PATH 並沒有加入 /sbin

# 所以,未來你找不到某些指令時,先用檔案搜尋指令找找看再說!

 

 

Locate

這個 locate 的使用更簡單,直接在後面輸入『檔案的部分名稱』後,就能夠得到結果。但是,在使用上還是會有一些限制的。因為他是經由資料庫來搜尋的,而資料庫的建立預設是在每天執行一次 (每個distribution 都不同,CentOS 5.x 是每天更新資料庫一次!) 所以當你新建立起來的檔案,卻還在資料庫更新之前搜尋該檔案,那麼 locate 會告訴你『找不到!』因此必須要更新資料庫。

 

那如何手動更新資料庫呢?更新 locate 資料庫的方法非常簡單,直接輸入『 updatedb 』就可以了!updatedb指令會去讀取 /etc/updatedb.conf 這個設定檔的設定,然後再去硬碟裡面進行搜尋檔名的動作,最後就更新整個資料庫檔案囉!因為 updatedb 會去搜尋硬碟,所以當你執行 updatedb 時,可能會等待數分鐘的時間喔!

  • updatedb:根據 /etc/updatedb.conf 的設定去搜尋系統硬碟內的檔名,                                                    並更新 /var/lib/mlocate 內的資料庫檔案;
  • locate:依據 /var/lib/mlocate 內的資料庫記載,找出使用者輸入的關鍵字檔名。

你會發現使用 locate 來尋找資料的時候特別的快,這是因為 locate 尋找的資料是由『已建立的資料庫 /var/lib/mlocate/』 裡面的資料所搜尋到的,所以不用直接在去硬碟當中存取資料!

 

[root@www ~]# locate [-ir] keyword

選項與參數:

-i  :忽略大小寫的差異;

-r  :後面可接正規表示法的顯示方式

 

 

Find

find是直接從硬碟做查詢的動作,在查詢的方式有很多種。以下就是一些範例參考。

 

時間參數

[root@www ~]# find [PATH] [option] [action]

選項與參數:

1. 與時間有關的選項:共有 -atime, -ctime -mtime ,以 -mtime 說明

   -mtime  n n 為數字,意義為在 n 天之前的『一天之內』被更動過內容的檔案;

   -mtime +n :列出在 n 天之前(不含 n 天本身)被更動過內容的檔案檔名;

   -mtime -n :列出在 n 天之內( n 天本身)被更動過內容的檔案檔名。

-newer file file 為一個存在的檔案,列出比 file 還要新的檔案檔名

 

範例一:將過去系統上面 24 小時內有更動過內容 (mtime) 的檔案列出

[root@www ~]# find / -mtime 0

# 那個 0 是重點!0 代表目前的時間,所以,從現在開始到 24 小時前,

# 有變動過內容的檔案都會被列出來!那如果是三天前的 24 小時內?

# find / -mtime 3 有變動過的檔案都被列出的意思!

 

範例二:尋找 /etc 底下的檔案,如果檔案日期比 /etc/passwd 新就列出

[root@www ~]# find /etc -newer /etc/passwd

# -newer 用在分辨兩個檔案之間的新舊關係是很有用的!

 

現在知道 atime, ctime mtime 的意義

如果要找出一天內被更動過的檔案名稱,可以使用上述範例一的作法。

如果要找出『4天內被更動過的檔案檔名』那就可以使用『find /var -mtime -4 』。

那如果是『4天前的那一天』就用『find /var -mtime 4 』。

有沒有加上『+, -』差別很大喔!可以用簡單的圖示來說明一下:


 

圖中最右邊為目前的時間,越往左邊則代表越早之前的時間軸啦。由上圖可以清楚的知道:

  • +4代表大於等於5天前的檔名:ex> find /var -mtime +4
  • -4代表小於等於4天內的檔案檔名:ex> find /var -mtime -4
  • 4則是代表4-5那一天的檔案檔名:ex> find /var -mtime 4

 

 

使用者或群組名稱的參數

想找出某個使用者在系統底下建立了什麼,可參考下列的選項與參數

 

項與參數:

2. 與使用者或群組名稱有關的參數:

   -uid n n 為數字,這個數字是使用者的帳號 ID,亦即 UID ,這個 UID 是記錄在

            /etc/passwd 裡面與帳號名稱對應的數字。這方面我們會在第四篇介紹。

   -gid n n 為數字,這個數字是群組名稱的 ID,亦即 GID,這個 GID 記錄在

            /etc/group,相關的介紹我們會第四篇說明~

   -user name name 為使用者帳號名稱喔!例如 dmtsai

   -group namename 為群組名稱喔,例如 users

   -nouser    :尋找檔案的擁有者不存在 /etc/passwd 的人!

   -nogroup   :尋找檔案的擁有群組不存在於 /etc/group 的檔案!

                當你自行安裝軟體時,很可能該軟體的屬性當中並沒有檔案擁有者,

                這是可能的!在這個時候,就可以使用 -nouser -nogroup 搜尋。

 

範例三:搜尋 /home 底下屬於 derek 的檔案

[root@www ~]# find /home -user derek

# 這個東西也很有用的~當我們要找出任何一個使用者在系統當中的所有檔案時,

# 就可以利用這個指令將屬於某個使用者的所有檔案都找出來喔!

 

範例四:搜尋系統中不屬於任何人的檔案

[root@www ~]# find / -nouser

# 透過這個指令,可以輕易的就找出那些不太正常的檔案。

# 如果有找到不屬於系統任何人的檔案時,不要太緊張,

# 那有時候是正常的~尤其是你曾經以原始碼自行編譯軟體時。

 

 

參數中的-nouser -nogroup 的選項功能中,除了自行從網路上下載檔案時會發生之外,如果將系統內某個帳號刪除,但是該帳號已經在系統內建立很多檔案時,就可能會發生檔案存在但是擁有者或擁有群組不存在的情況!這個時後就可使用 -nouser 來找出該類型的檔案!

 

 檔案權限及名稱的參數

選項與參數:

3. 與檔案權限及名稱有關的參數:

   -name filename:搜尋檔案名稱為 filename 的檔案;

   -size [+-]SIZE:搜尋比 SIZE 還要大(+)或小(-)的檔案。這個 SIZE 的規格有:

                   c: 代表 byte k: 代表 1024bytes。所以,要找比 50KB

                   還要大的檔案,就是『 -size +50k

   -type TYPE    :搜尋檔案的類型為 TYPE 的,類型主要有:一般正規檔案 (f),

                   裝置檔案 (b, c), 目錄 (d), 連結檔 (l), socket (s),

                   FIFO (p) 等屬性。

   -perm mode  :搜尋檔案權限『剛好等於』 mode 的檔案,這個 mode 為類似 chmod

                 的屬性值,舉例來說, -rwsr-xr-x 的屬性為 4755

   -perm -mode :搜尋檔案權限『必須要全部囊括 mode 的權限』的檔案,舉例來說,

                 我們要搜尋 -rwxr–r– ,亦即 0744 的檔案,使用 -perm -0744

                 當一個檔案的權限為 -rwsr-xr-x ,亦即 4755 時,也會被列出來,

                 因為 -rwsr-xr-x 的屬性已經囊括了 -rwxr–r– 的屬性了。

   -perm +mode :搜尋檔案權限『包含任一 mode 的權限』的檔案,舉例來說,我們搜尋

                 -rwxr-xr-x ,亦即 -perm +755 時,但一個檔案屬性為 -rw——-

                 也會被列出來,因為他有 -rw…. 的屬性存在!

    -perm 這個參數,重點在找出特殊權限的檔案

         

範例五:找出檔名為 passwd 這個檔案

[root@www ~]# find / -name passwd

# 利用這個 -name 可以搜尋檔名啊!

 

範例六:找出 /var 目錄下,檔案類型為 Socket 的檔名有哪些?

[root@www ~]# find /var -type s

# 這個 -type 的屬性也很有幫助喔!尤其是要找出那些怪異的檔案,

# 例如 socket FIFO 檔案,可以用 find /var -type p -type s 來找!

 

範例七:搜尋檔案當中含有 SGID SUID SBIT 的屬性

[root@www ~]# find / -perm +7000

# 所謂的 7000 就是 —s–s–t ,那麼只要含有 s t 的就列出,

# 所以當然要使用 +7000 ,使用 -7000 表示要含有 —s–s–t 的所有三個權限,

# 因此,就是 +7000

 

 

我們知道 SUID SGID 都可以設定在二進位程式上,假設想要找出來 /bin, /sbin 這兩個目錄下,只要具有 SUID SGID 就列出來該檔案,可以這樣做。

[root@www ~]# find /bin /sbin -perm +6000

 

因為 SUID 4 分,SGID 2 分,總共為 6 分,因此可用 +6000 來處理這個權限! 至於 find 後面可以接多個目錄來進行搜尋!另外, find 本來就會搜尋次目錄,這個特色也要特別注意

 

 

額外可進行的動作

選項與參數:

4. 額外可進行的動作:

   -exec command command 為其他指令,-exec 後面可再接額外的指令來處理搜尋到

                   的結果。

   -print        :將結果列印到螢幕上,這個動作是預設動作!

 

範例八:將上個範例找到的檔案使用 ls -l 列出來~

[root@www ~]# find / -perm +7000 -exec ls -l {} \;

# 注意到,那個 -exec 後面的 ls -l 就是額外的指令,指令不支援命令別名,

# 所以僅能使用 ls -l 不可以使用 ll 喔!注意注意!

 

範例九:找出系統中,大於 1MB 的檔案

[root@www ~]# find / -size +1000k

# 雖然在 man page 提到可以使用 M G 分別代表 MB GB


find 的特殊功能就是能夠進行額外的動作(action)。將範例八的例子以圖解來說明如下:


該範例中特殊的地方有 {} 以及 \; 還有 -exec 這個關鍵字,這些東西的意義為:

  • {} 代表的是『由 find 找到的內容』,如上圖所示,find 的結果會被放置到 {} 位置中;
  • -exec 一直到 \; 是關鍵字,代表 find 額外動作的開始 (-exec) 到結束 (\;) ,在這中間的就是 find 指令內的額外動作。 在本例中就是『 ls -l {} 』囉!
  • 因為『 ; 』在 bash 環境下是有特殊意義的,因此利用反斜線來跳脫。

如果你要找的檔案是具有特殊屬性的,例如 SUID 、檔案擁有者、檔案大小等等, 那麼利用 locate 沒有辦法達成你的搜尋的!此時 find 就顯的很重要! 另外,find 還可以利用萬用字元來找尋檔名呢!

舉例來說,你想要找出 /etc 底下檔名包含 httpd 的檔案, 那麼你就可以這樣做:

[root@www ~]# find /etc -name '*httpd*'

 

不但可以指定搜尋的目錄(連同次目錄),並且可以利用額外的選項與參數來找到最正確的檔名!真是好好用! 不過由於 find 在尋找資料的時後相當的操硬碟!所以沒事情不要使用 find !有更棒的指令可以取代呦!那就是上面提到的 whereis  locate 

 

 

 

以上內容為參考 鳥哥 整理出來的,如果想要更詳細了解可直接參考 鳥哥 第七章檔案與目錄管理

 

 

 

 

關於作者

一個半路殺出來的傻小子,憑著一股傻勁努力的學習、嘗試、分享。希望能用自己微薄之力,替IT界和資訊界盡一點心力。單憑一己之力始終還是有限,歡迎和我有相同理念的夥伴一同加入一同努力。

評論

  1. Anja Likos 說: 2011/05/29

    Thanks for some quality points there. I am kind of new to online , so I printed this off to put in my file, any better way to go about keeping track of it then printing?

發表評論至 Anja Likos

*