Linux探索之旅 | 第二部分第九課:查詢檔案,無所遁形

程式設計師聯盟發表於2017-04-05

Linux探索之旅 | 第二部分第九課:查詢檔案,無所遁形

-- 作者 謝恩銘 轉載請註明出處

內容簡介


  1. 第二部分第九課:查詢檔案,無所遁形
  2. 第二部分第十課預告:第二部分測試題

查詢檔案,無所遁形


上一課 Linux探索之旅 | 第二部分第八課:RTFM 閱讀那該死的手冊,我們學習了很重要的技能:如何閱讀使用手冊。

這一課不難,但挺重要的。

之前的課程Linux探索之旅 | 第二部分第三課:檔案和目錄,組織不會虧待你中,我們已經見識過,Linux下檔案的組織形式是很特別的,跟Windows不一樣。

我們也用ls / 這個命令來列出根目錄下的所有目錄,有/bin,/etc,/var,/home,等等。而這些目錄下又有子目錄和檔案,錯綜複雜。

ls /複製程式碼

這些目錄中有一部分是歷史遺留的,從Unix時代就有了。問題是:我們如何在這“茫茫文海”中查詢我們需要的檔案。

“人潮人海中,有你有我。相遇相識,相互琢磨”(黑豹樂隊的《無地自容》),小編你可以了...

不要擔心,這一課我們就來學習Linux中用於檔案查詢的工具。

有的工具查詢起來快,但是不全面;有的比較慢,但是全面。

一起來學習吧。

locate命令,快速查詢


第一種查詢檔案的方法可以說是很簡單的。用到的命令是locate。

locate是英語“定位”的意思。這個命令用於定位要查詢的檔案,而且此命令很快。

locate命令的用法也很直觀,後接需要查詢的檔名(當然也可以用正規表示式)。

例如我們來查詢一個叫做 renamed_file的檔案:

locate renamed_file複製程式碼

Linux探索之旅 | 第二部分第九課:查詢檔案,無所遁形

可以看到locate命令幫我們找到了renamed_file檔案,位於 /home/oscar/linux_c目錄下。

我們再來用locate查詢france檔案(France是“法國”的意思。):

Linux探索之旅 | 第二部分第九課:查詢檔案,無所遁形

我們執行locate france後,終端列出了所有包含france的檔案和目錄。

所以locate命令是搜尋包含關鍵字的所有檔案和目錄。

檔案的資料庫


在使用locate命令查詢檔案時,大家可能會遇到這樣的問題:我剛建立的檔案,為什麼用locate命令查詢不到呢?

這正好是locate命令的缺陷,我正要說到:locate命令不會對你實際的整個硬碟進行查詢,而是在檔案的資料庫裡查詢記錄。

locate命令的原理如下圖所示:

Linux探索之旅 | 第二部分第九課:查詢檔案,無所遁形

對於剛建立不久的檔案,因為它們還沒被收錄進檔案資料庫,因此locate命令就找不到其索引,自然就不會返回任何結果。

Linux系統一般每天會更新一次檔案資料庫。因此,只要你隔24小時再用locate查詢,應該就能找到你剛建立的檔案了。

但是你會說:“臣妾不想等這麼久啊。難道哀家要在這深宮之中等候多時麼?”

當然不是,甄嬛不會一直贏的,皇后總有出頭之日。

我們可以用updatedb命令強制系統立即更新檔案資料庫。但是updatedb命令只能由root使用者執行。

update是英語“更新”的意思。db是英語database的縮寫,表示“資料庫”。所以連起來就是“更新資料庫”。

因此我們可以這樣:

sudo updatedb複製程式碼

這個命令執行需要一點時間,小編執行的時候等了幾分鐘才完畢。

一旦執行成功,你再用locate查詢你剛才建立的檔案,就可以找到了。

總結一下:locate命令方便快捷,易於使用。但缺點也很明顯:

  1. locate命令會列出所有在檔案資料庫中找到的內容,有時候結果太多了,太繁雜。

  2. locate命令不能找到一天之內剛建立的檔案,除非你先用root身份執行updatedb命令來更新檔案資料庫。

  3. 當locate命令不夠用時,我們需要一個更強大的命令,它就是find命令。

find命令,深入查詢


find是英語“找到”的意思,find命令也用於查詢檔案。

find命令是查詢檔案的利器,而且它可以讓我們對每個找到的檔案做後續的操作。find命令非常強大,可以做很多事情,因此也比較複雜。

find命令可以說是Linux中最常用的命令之一了。所以,一起來探祕吧。

find命令查詢當前實際的檔案


與locate命令不同,find命令不會在檔案資料庫中查詢檔案的記錄,而是遍歷你的實際硬碟。

所以,如果你的硬碟容量很大的話,那find命令會查詢比較久。

find命令的原理如下圖所示:

Linux探索之旅 | 第二部分第九課:查詢檔案,無所遁形

find命令的這種“耿直”的查詢方式保證了我們不會遺漏一天之內建立的檔案。但這絕對不是find的唯一強大之處,遠遠不是。

find命令的功能


find命令的用法是這樣的:

find 《何處》《何物》《做什麼》複製程式碼

這幾個引數中,只有《何物》是必須指定的,也就是要查詢什麼。

  • 何處:指定在哪個目錄中查詢。此目錄的所有子目錄也會被查詢。與locate命令的查詢所有檔案資料庫的所有記錄不同,find命令可以限定查詢目錄,比如我們可以只讓find查詢/home目錄。預設地,假如我們沒有給出《何處》這個引數,那麼find命令會在當前目錄及其子目錄中查詢。

  • 何物:也就是要查詢什麼。我們可以根據檔案的名字來查詢,也可以根據其大小來查詢,也可以根據其最近訪問時間來查詢,等等。這個引數是必須的。

  • 做什麼:用find命令找到我們要的檔案後,可以對每個檔案做一定的操作,稱為“後續處理”。預設地,假如不指定這個引數,那麼find命令只會顯示找到的檔案,不會做其他事情。

find命令的基礎用法


根據檔名查詢

我們首先來學習最基本的查詢:用檔名來查詢。

首先,我們定位到使用者的家目錄中(對於小編來說是/home/oscar),然後我要在當前目錄及其子目錄中查詢france1.jpg這個檔案。

find -name "france1.jpg"複製程式碼

Linux探索之旅 | 第二部分第九課:查詢檔案,無所遁形

這裡,我們用-name引數指定了檔名字,是france1.jpg,用雙引號括起來。不加雙引號或者用單引號也是可以的。

name是英語“名字”的意思。

經過了一點時間,查詢才停止,因為find命令會遍歷指定的所有目錄。

最終,find命令找到了france1.jpg這個檔案,位於/home/oscar/Photos 目錄下。

如果find命令沒有結果顯示,那麼表示此檔案不存在。

因為我們沒有指定《何處》這個引數,所以find命令就會在當前目錄(~,也就是使用者的家目錄中,/home/oscar)及其子目錄中查詢。

假如,現在我位於我的家目錄中,我卻想在其他目錄中進行查詢,怎麼辦呢?

那就須要指定《何處》這個引數了。

例如,我要在/var/log目錄下查詢名為syslog的檔案,我應該這麼輸入:

find /var/log "syslog"複製程式碼

Linux探索之旅 | 第二部分第九課:查詢檔案,無所遁形

但是,作為普通使用者的oscar,沒有許可權在/var/log的子目錄中查詢。因此,顯示:

Permission denied複製程式碼

permission是“許可”的意思,denied是“否決”的意思。就是說“許可權被否決”,沒有許可權做這事。

我們可以切換成root身份,再來執行查詢。

sudo su

find /var/log "syslog"複製程式碼

Linux探索之旅 | 第二部分第九課:查詢檔案,無所遁形

可以看到,切換成root後,就可以查詢了。並且找到了兩個結果:

/var/log/installer/syslog
/var/log/syslog複製程式碼

在上面的查詢中,我們的引數如下:

  • 何處:/var/log(及它的子目錄)

  • 何物:syslog

  • 沒有指定《做什麼》引數,因此find命令預設顯示了查詢到的檔案。

我們注意到了:與locate命令不同的是,find命令只會查詢完全符合《何物》的字串表示的檔案。locate會查詢所有包含關鍵字的檔案。比如,如果要用find來找thing這個檔案,那麼只會找到名字就是thing的檔案;而locate命令會查詢到比如thing,thing1,onething,twothings這樣的檔案。

因此,我們用find查詢syslog檔案時,就不會查詢到syslog2這樣的檔案。

不過我們可以用我們之前學過的萬用字元:*(星號)來實現匹配多個名稱。

例如,我要查詢所有以syslog這個關鍵字開頭的檔案,可以這樣來實現:

find /var/log -name "syslog*"複製程式碼

Linux探索之旅 | 第二部分第九課:查詢檔案,無所遁形

可以看到,在syslog之後加了之後,就會匹配凡是以syslog開頭的檔案了,因為號是匹配一個或多個任意字元。

那聰明如你肯定想到了,如果要查詢以syslog結尾的檔案,可以用:*syslog

那你肯定也知道,如何查詢包含syslog這個關鍵字的檔案,可以用 *syslog*

那如果我要在整個硬碟裡查詢怎麼做呢?很簡單:

find / -name "syslog"複製程式碼

在Linux的根目錄查詢很花時間,而且,如果你不是以root身份查詢的話,就會有很多目錄提示你“無許可權訪問”。

根據檔案大小查詢


如果你不知道你要找的檔案的名稱,那怎麼辦呢?

不要擔心,還有其他方式來查詢檔案的。

我們先來看如何根據檔案大小查詢。

例如,我們可以查詢/var中大小超過10M的檔案(當然你要以root身份):

find /var -size +10M複製程式碼

Linux探索之旅 | 第二部分第九課:查詢檔案,無所遁形

這次,我們使用了-size引數,來指定查詢檔案的大小。size是英語“尺寸,大小”的意思。

後面緊跟的+10M表示大於10兆位元組。

M是兆,也就是10的6次方;平時我們所說的Ko,Mo,Go其實分別是千位元組,兆位元組,千兆位元組的意思。

一個位元組是8位二進位制數。我們說硬碟512G,就是硬碟容量有512千兆位元組(雖然實際容量是不到的,暫時不深究)。

如果我們要查詢小於指定大小的檔案,可以用減號。例如:

find /var -size -50K複製程式碼

表示查詢小於50Ko的檔案。

find /var -size +20G複製程式碼

表示查詢大於20Go的檔案。

如果沒有加減號,則查詢大小等於指定數值的檔案。

根據檔案的最近訪問時間查詢


如果你記得你近7天裡在家目錄中訪問過JPG格式的圖片,但是你忘記它們的名字了,如何查詢呢?

可以使用-atime引數。atime是access和time的縮寫,access是英語“訪問,進入”的意思,time是英語“時間”的意思。

可以這樣查詢:

find -name "*.jpg" -atime -7複製程式碼

Linux探索之旅 | 第二部分第九課:查詢檔案,無所遁形

-atime引數後面緊跟的-7表示7天之內,減號的作用是表示小於。

僅查詢目錄或檔案


我們可以指定查詢的檔案型別,我們知道Linux中檔案的型別大致分為兩種:目錄和檔案。

因此,我們可以用-type引數來指定查詢的檔案型別。type是英語“型別”的意思。

  • -type d:只查詢目錄型別。d是directory的首字母,表示“目錄”。

  • -type f:只查詢檔案型別。f是file的首字母,表示“檔案”。

如果不用-type引數指定型別,那麼find命令預設是查詢目錄和檔案的。比如說,有syslog這個檔案,和syslog這個目錄,那麼find會把他們都查詢出來。

用法如下:

find /var/log -name "mysql" -type d複製程式碼

Linux探索之旅 | 第二部分第九課:查詢檔案,無所遁形

可以看到只查詢到了mysql這個目錄。

find命令的高階用法:操作查詢結果


到目前為止,我們只是使用了find的基本功能。我們並沒有指定《做什麼》這個引數,也就是還沒對查詢到的結果做任何操作。

當然了,預設地,find命令會顯示每個查詢到的檔案。

事實上,

find -name "*.jpg"複製程式碼

等價於

find -name "*.jpg" -print複製程式碼

-print引數用於列印結果。print是英語“列印”的意思。

格式化列印查詢結果


預設地,find命令只列出查詢到的檔案,但是我們可以將其用格式化的方式列印出來。**

我們可以使用-printf引數。是不是想起了C語言中的printf函式?是的,printf是print formatted的縮寫,表示“格式化列印”。

例如,我們可以這樣列印查詢到的內容:

find ~/Photos -name "*.jpg" -printf "%p - %u\n"複製程式碼

Linux探索之旅 | 第二部分第九課:查詢檔案,無所遁形

我們在-printf引數後面寫了"%p - %u\n",這個格式字串的意思如下:

  • %p:檔名。

  • -:就是一個短橫。

  • %u:檔案的所有者,這裡是小編的使用者名稱,所以是oscar。

  • \n:用於換行。

可以看到,用法和C語言的printf函式很類似。

刪除查詢到的檔案


假如我要刪除查詢到的檔案,我可以用-delete引數。用法很簡單:

find -name "*.jpg" -delete複製程式碼

將會刪除當前目錄及其子目錄下所有以.jpg為字尾的檔案。而且不會有確認提示。所以慎用-delete引數。

呼叫命令


使用-exec引數,可以後接一個命令,對每個查詢到的檔案進行操作。

exec是execute的縮寫,是英語“執行”的意思。

假設我想要將當前目錄下所有查詢到的JPG檔案的訪問許可權都改為600,那麼我們可以這樣做:

find -name "*.jpg" -exec chmod 600 {} \;複製程式碼

就是說對於每個找到的.jpg結尾的檔案,都進行-exec引數指定的操作:

  • 這個操作不必用雙引號括起來。

  • {} 會用查詢到的每個檔案來替換。

  • \; 是必須的結尾。

雖然-exec引數一開始有點看不懂其用法,但是慢慢地你會發現,這個引數太強大了,你可以對查詢到的檔案做任何你想要的操作。

如果你對於沒有確認提示不太放心,你可以將-exec引數換成-ok引數,用法一樣,只不過-ok引數會對每一個查詢到的檔案都做確認提示,輸入y加回車表示對此檔案進行此操作;輸入n加回車表示對此檔案不進行此操作。

總結


  1. 為了在Linux硬碟中查詢一個檔案,我們可以用locate命令。這個命令很快,因為它不會實際遍歷硬碟,而是在被稱為檔案資料庫的記錄裡查詢,所以它找不到剛新增的檔案。為了更新檔案資料庫,我們可以用root使用者身份執行updatedb命令。

  2. find命令比locate命令更強大,用法更多樣。它會遍歷實際的硬碟來查詢檔案,所以更慢,但是更精確。find命令可以跟三個引數:《何處》,《何物》,《做什麼》。

  3. 可以根據檔案的名字來查詢,用-name引數;根據大小來查詢,用-size引數;根據最後訪問時間來查詢,用-atime引數。等等。

  4. 查詢到了檔案,我們也可以選擇不顯示,而是刪除檔案,用-delete引數,或者對檔案執行命令,用-exec引數。

第二部分測試題預告


今天的課就到這裡,一起加油吧!

下一課:Linux探索之旅 | 第二部分測試題


微信公眾號「程式設計師聯盟」ProgrammerLeague
我是謝恩銘,在巴黎奮鬥的軟體工程師。
我的簡介
我的經歷
熱愛生活,喜歡游泳,略懂烹飪。
人生格言:“向著標杆直跑”

相關文章