實用的Linux find命令示例

http://blog.jobbole.com/48856/

首先,在你的home目錄下面創建下面的空文件,來測試下面的find命令示例。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# vim create_sample_files.sh
touch MybashProgram.sh
touch mycprogram.c
touch MyCProgram.c
touch Program.c
mkdir backup
cd backup
touch MybashProgram.sh
touch mycprogram.c
touch MyCProgram.c
touch Program.c
# chmod +x create_sample_files.sh
# ./create_sample_files.sh
# ls -R
.:
backup                  MybashProgram.sh  MyCProgram.c
create_sample_files.sh  mycprogram.c      Program.c
./backup:
MybashProgram.sh  mycprogram.c  MyCProgram.c  Program.c

1. 用文件名查找文件

這是find命令的一個基本用法。下面的例子展示了用MyCProgram.c作爲查找名在當前目錄及其子目錄中查找文件的方法。

1
2
3
# find -name "MyCProgram.c"
./backup/MyCProgram.c
./MyCProgram.c

2.用文件名查找文件,忽略大小寫

這是find命令的一個基本用法。下面的例子展示了用MyCProgram.c作爲查找名在當前目錄及其子目錄中查找文件的方法,忽略了大小寫。

1
2
3
4
5
# find -iname "MyCProgram.c"
./mycprogram.c
./backup/mycprogram.c
./backup/MyCProgram.c
./MyCProgram.c

 

3. 使用mindepth和maxdepth限定搜索指定目錄的深度

在root目錄及其子目錄下查找passwd文件。

1
2
3
4
5
# find / -name passwd
./usr/share/doc/nss_ldap-253/pam.d/passwd
./usr/bin/passwd
./etc/pam.d/passwd
./etc/passwd

在root目錄及其1層深的子目錄中查找passwd. (例如root — level 1, and one sub-directory — level 2)

1
2
# find -maxdepth 2 -name passwd
./etc/passwd

在root目錄下及其最大兩層深度的子目錄中查找passwd文件. (例如 root — level 1, and two sub-directories — level 2 and 3 )

1
2
3
4
# find / -maxdepth 3 -name passwd
./usr/bin/passwd
./etc/pam.d/passwd
./etc/passwd

在第二層子目錄和第四層子目錄之間查找passwd文件。

1
2
3
# find -mindepth 3 -maxdepth 5 -name passwd
./usr/bin/passwd
./etc/pam.d/passwd

4. 在find命令查找到的文件上執行命令

下面的例子展示了find命令來計算所有不區分大小寫的文件名爲“MyCProgram.c”的文件的MD5驗證和。{}將會被當前文件名取代。

1
2
3
4
5
find -iname "MyCProgram.c" -exec md5sum {} \;
d41d8cd98f00b204e9800998ecf8427e  ./mycprogram.c
d41d8cd98f00b204e9800998ecf8427e  ./backup/mycprogram.c
d41d8cd98f00b204e9800998ecf8427e  ./backup/MyCProgram.c
d41d8cd98f00b204e9800998ecf8427e  ./MyCProgram.c

5. 相反匹配

顯示所有的名字不是MyCProgram.c的文件或者目錄。由於maxdepth是1,所以只會顯示當前目錄下的文件和目錄。

1
2
3
4
5
6
find -maxdepth 1 -not -iname "MyCProgram.c"
.
./MybashProgram.sh
./create_sample_files.sh
./backup
./Program.c

6. 使用inode編號查找文件

任何一個文件都有一個獨一無二的inode編號,藉此我們可以區分文件。創建兩個名字相似的文件,例如一個有空格結尾,一個沒有。

1
2
3
4
5
6
touch "test-file-name"
# touch "test-file-name "
[Note: There is a space at the end]
# ls -1 test*
test-file-name
test-file-name

從ls的輸出不能區分哪個文件有空格結尾。使用選項-i,可以看到文件的inode編號,藉此可以區分這兩個文件。

1
2
3
ls -i1 test*
16187429 test-file-name
16187430 test-file-name

你可以如下面所示在find命令中指定inode編號。在此,find命令用inode編號重命名了一個文件。

1
2
3
4
5
find -inum 16187430 -exec mv {} new-test-file-name \;
 
 # ls -i1 *test*
16187430 new-test-file-name
16187429 test-file-name

你可以在你想對那些像上面一樣的糟糕命名的文件做某些操作時使用這一技術。例如,名爲file?.txt的文件名字中有一個特殊字符。若你想執行“rm file?.txt”,下面所示的所有三個文件都會被刪除。所以,採用下面的步驟來刪除”file?.txt”文件。

1
2
ls
file1.txt  file2.txt  file?.txt

找到每一個文件的inode編號。

1
2
3
4
ls -i1
804178 file1.txt
804179 file2.txt
804180 file?.txt

如下所示:?使用inode編號來刪除那些具有特殊符號的文件名。

1
2
3
4
find -inum 804180 -exec rm {} \;
# ls
file1.txt  file2.txt
[Note: The file with name "file?.txt" is now removed]

7. 根據文件權限查找文件

下面的操作時合理的:

  • 找到具有指定權限的文件
  • 忽略其他權限位,檢查是否和指定權限匹配
  • 根據給定的八進制/符號表達的權限搜索

此例中,假設目錄包含以下文件。注意這些文件的權限不同。

1
2
3
4
5
6
7
8
ls -l
total 0
-rwxrwxrwx 1 root root 0 2009-02-19 20:31 all_for_all
-rw-r--r-- 1 root root 0 2009-02-19 20:30 everybody_read
---------- 1 root root 0 2009-02-19 20:31 no_for_all
-rw------- 1 root root 0 2009-02-19 20:29 ordinary_file
-rw-r----- 1 root root 0 2009-02-19 20:27 others_can_also_read
----r----- 1 root root 0 2009-02-19 20:27 others_can_only_read

找到具有組讀權限的文件。使用下面的命令來找到當前目錄下對同組用戶具有讀權限的文件,忽略該文件的其他權限。

1
2
3
4
5
find . -perm -g=r -type f -exec ls -l {} \;
-rw-r--r-- 1 root root 0 2009-02-19 20:30 ./everybody_read
-rwxrwxrwx 1 root root 0 2009-02-19 20:31 ./all_for_all
----r----- 1 root root 0 2009-02-19 20:27 ./others_can_only_read
-rw-r----- 1 root root 0 2009-02-19 20:27 ./others_can_also_read

找到對組用戶具有隻讀權限的文件。

1
2
find . -perm g=r -type f -exec ls -l {} \;
----r----- 1 root root 0 2009-02-19 20:27 ./others_can_only_read

找到對組用戶具有隻讀權限的文件(使用八進制權限形式)。

1
2
find . -perm 040 -type f -exec ls -l {} \;
----r----- 1 root root 0 2009-02-19 20:27 ./others_can_only_read

8. 找到home目錄及子目錄下所有的空文件(0字節文件)

下面命令的輸出文件絕大多數都是鎖定文件盒其他程序創建的place hoders

1
find ~ -empty

只列出你home目錄裏的空文件。

1
find . -maxdepth 1 -empty

只列出當年目錄下的非隱藏空文件。

1
find . -maxdepth 1 -empty -not -name ".*"

9. 查找5個最大的文件

下面的命令列出當前目錄及子目錄下的5個最大的文件。這會需要一點時間,取決於命令需要處理的文件數量。

1
find . -type f -exec ls -s {} \; | sort -n -r | head -5

10. 查找5個最小的文件

方法同查找5個最大的文件類似,區別只是sort的順序是降序。

1
find . -type f -exec ls -s {} \; | sort -n  | head -5

上面的命令中,很可能你看到的只是空文件(0字節文件)。如此,你可以使用下面的命令列出最小的文件,而不是0字節文件。

1
find . -not -empty -type f -exec ls -s {} \; | sort -n  | head -5

11. 使用-type查找指定文件類型的文件

只查找socket文件

1
find . -type s

查找所有的目錄

1
find . -type d

查找所有的一般文件

1
find . -type f

查找所有的隱藏文件

1
find . -type f -name ".*"

查找所有的隱藏目錄

1
find -type d -name ".*"

12. 通過和其他文件比較修改時間查找文件

顯示在指定文件之後做出修改的文件。下面的find命令將顯示所有的在ordinary_file之後創建修改的文件。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
ls -lrt
total 0
-rw-r----- 1 root root 0 2009-02-19 20:27 others_can_also_read
----r----- 1 root root 0 2009-02-19 20:27 others_can_only_read
-rw------- 1 root root 0 2009-02-19 20:29 ordinary_file
-rw-r--r-- 1 root root 0 2009-02-19 20:30 everybody_read
-rwxrwxrwx 1 root root 0 2009-02-19 20:31 all_for_all
---------- 1 root root 0 2009-02-19 20:31 no_for_all
 
# find -newer ordinary_file
.
./everybody_read
./all_for_all
./no_for_all

13. 通過文件大小查找文件

使用-size選項可以通過文件大小查找文件。

查找比指定文件大的文件

1
find ~ -size +100M

查找比指定文件小的文件

1
find ~ -size -100M

查找符合給定大小的文件

1
find ~ -size 100M

注意: – 指比給定尺寸小,+ 指比給定尺寸大。沒有符號代表和給定尺寸完全一樣大。

14. 給常用find操作取別名

若你發現有些東西很有用,你可以給他取別名。並且在任何你希望的地方執行。

常用的刪除a.out文件。

1
2
alias rmao="find . -iname a.out -exec rm {} \;"
# rmao

刪除c程序產生的core文件。

1
2
alias rmc="find . -iname core -exec rm {} \;"
# rmc

15. 用find命令刪除大型打包文件

下面的命令刪除大於100M的*.zip文件。

1
find / -type f -name *.zip -size +100M -exec rm -i {} \;"

用別名rm100m刪除所有大雨100M的*.tar文件。使用同樣的思想可以創建rm1g,rm2g,rm5g的一類別名來刪除所有大於1G,2G,5G的文件。

1
2
3
4
5
6
7
8
9
alias rm100m="find / -type f -name *.tar -size +100M -exec rm -i {} \;"
# alias rm1g="find / -type f -name *.tar -size +1G -exec rm -i {} \;"
# alias rm2g="find / -type f -name *.tar -size +2G -exec rm -i {} \;"
# alias rm5g="find / -type f -name *.tar -size +5G -exec rm -i {} \;"
 
# rm100m
# rm1g
# rm2g
# rm5g

基於訪問/修改/更改時間查找文件

你可以找到基於以下三個文件的時間屬性的文件。

  1. 訪問時間的文件。文件訪問時,訪問時間得到更新。
  2. 的文件的修改時間文件內容修改時,修改時間得到更新。
  3. 更改文件的時間。更改時間時,被更新的inode數據的變化

在下面的例子中,min選項之間的差異和時間選項是參數。

  • 分論點將它的參數爲分鐘。例如,60分鐘(1小時)= 60分鐘。
  • 時間參數,將它的參數爲24小時。例如,時間2 = 2 * 24小時(2天)。
  • 雖然這樣做的24個小時計算,小數部分都將被忽略,所以25小時爲24小時,和47小時取爲24小時,僅48小時爲48小時。要獲得更清晰的參考atime的部分find命令的手冊頁。

例1:找到在1個小時內被更改的文件

想要通過文件修改時間找出文件,可以使用參數 -mmin -mtime。下面是man手冊中有關mmin和mtime的定義。

  • -mmin n 文件最後一次修改是在n分鐘之內
  • -mtime n 文件最後一次修改是在 n*24小時之內(譯者注:也就是n天了唄)

執行下面例子中的命令,將會找到當前目錄以及其子目錄下,最近一次修改時間在1個小時(60分鐘)之內的文件或目錄

1
# find . -amin -60

同樣的方式,執行下面例子中的命令,將會找到24小時(1天)內被訪問了的文件(文件系統根目錄 / 下)

1
# find / -atime -1

例2:找到1個小時內被訪問過的文件

想要通過文件訪問時間找出文件,可以使用參數 -amin -atime。下面是man手冊中有關amin和atime的定義。

  • -amin n 文件最後一次訪問是在n分鐘之內
  • -atime n 文件最後一次訪問是在 n*24小時之內

執行下面例子中的命令,將會找到當前目錄以及其子目錄下,最近一次訪問時間在1個小時(60分鐘)之內的文件或目錄

1
# find . -amin -60

同樣的方式,執行下面例子中的命令,將會找到24小時(1天)內被訪問了的文件(文件系統根目錄 / 下)

1
# find / -atime -1

例3:查找一個小時內狀態被改變的文件

(譯者注:這裏的改變更第1個例子的更改文件內容時間是不同概念,這裏是更改的是文件inode的數據,比如文件的權限,所屬人等等信息)

要查找文件的inode的更改時間,使用-cmin和-ctime選項

  • -cmin n  文件的狀態在n分鐘內被改變
  • -ctime n  文件狀態在n*24小時內(也就是n天內)被改變

(譯者注:如果上面的n爲-n形式,則表示n分鐘/天之內,n爲+n則表示n分鐘/天之前)

下面的例子在當前目錄和其子目錄下面查找一個小時內文件狀態改變的文件(也就是60分鐘內):

1
# find . -cmin -60

同樣的道理,下面的例子在根目錄/及其子目錄下一天內(24小時內)文件狀態被改變的文件列表:

1
# find / -ctime -1

例4:搜索僅僅限定於文件,不顯示文件夾

上面的例子搜索出來不僅僅有文件,還會顯示文件夾。因爲當一個文件被訪問的時候,它所處的文件夾也會被訪問,如果你對文件夾不感興趣,那麼可以使用 -type f 選項

下面的例子會顯示30分鐘內被修改過的文件,文件夾不顯示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# find /etc/sysconfig -amin -30
.
./console
./network-scripts
./i18n
./rhn
./rhn/clientCaps.d
./networking
./networking/profiles
./networking/profiles/default
./networking/profiles/default/resolv.conf
./networking/profiles/default/hosts
./networking/devices
./apm-scripts
[注: 上面的輸出包含了文件和文件夾]
 
# find /etc/sysconfig -amin -30 -type f
./i18n
./networking/profiles/default/resolv.conf
./networking/profiles/default/hosts
[注: 上面的輸出僅僅包含文件]

例5: 僅僅查找非隱藏的文件(不顯示隱藏文件):

如果我們查找的時候不想隱藏文件也顯示出來,可以使用下面的正則式查找:

下面的命令會顯示當前目錄及其子目錄下15分鐘內文件內容被修改過的文件,並且只列出非隱藏文件。也就是說,以.開頭的文件時不會顯示出來的

1
# find . -mmin -15 <span class="MathJax_Preview">\( ! -regex ".*/\..*" \)</span><script type="math/tex"> ! -regex ".*/\..*" </script>

基於文件比較的查找命令

我們平時通過更別的東西進行比較,會更容易記住一些事情。比如說我想找出在我編輯test文件之後編輯過的文件。你可以通過test這個文件的編輯時間作爲比較基準去查找之後編輯過的文件:

例6: 查找文件修改時間在某一文件修改後的文件:

1
語法: find -newer FILE

下面的例子顯示在/etc/passwd修改之後被修改過的文件。對於系統管理員,想知道你新增了一個用戶後去跟蹤系統的活動狀態是很有幫助的(萬一那新用戶不老實,一上來就亂搞,你很快就知道了  ^_^):

1
# find -newer /etc/passwd

例7:查找文件訪問時間在某一文件的修改時間之後的文件:

1
# find -newer /etc/passwd

下面的例子顯示所有在/etc/hosts文件被修改後被訪問到的文件。如果你新增了一個主機/端口記錄在/etc/hosts文件中,你很可能很想知道在那之後有什麼文件被訪問到了,下面是這個命令:

1
# find -anewer /etc/hosts

例8:查找狀態改變時間在某個文件修改時間之後的文件:

1
語法: find -cnewer FILE

下面的例子顯示在修改文件/etc/fstab之後所有文件狀態改變過的文件。如果你在/etc/fstab新增了一個掛載點,你很可能想知道之後哪些文件的狀態發生了改變,這時候你可以使用如下命令:

1
# find -cnewer /etc/fstab

在查找到的文件列表結果上直接執行命令:

這之前你已經看到了如果通過find命令去查找各種條件的文件列表。如果你對這些find命令還不熟悉,我建議你看完上面的第一部分

接下來這部分我們向你介紹如果在find命令上執行各種不同的命令,也就是說如何去操作find命令查找出來的文件列表。

我們能在find命令查找出來的文件名列表上指定任意的操作:

1
# find <CONDITION to Find files> -exec <OPERATION> \;

其中的OPERATION可以是任意的命令,下面列舉一下比較常用的:

  •  rm 命令,用於刪除find查找出來的文件
  •  mv 命令,用於重命名查找出的文件
  •  ls -l 命令,顯示查找出的文件的詳細信息
  •  md5sum, 對查找出的文件進行md5sum運算,可以獲得一個字符串,用於檢測文件內容的合法性
  •  wc 命令,用於統計計算文件的單詞數量,文件大小等待
  •  執行任何Unix的shell命令
  •  執行你自己寫的shell腳本,參數就是每個查找出來的文件名

例9:在find命令輸出上使用 ls -l, 列舉出1小時內被編輯過的文件的詳細信息

1
2
3
4
5
6
7
# find -mmin -60
./cron
./secure
 
 # find -mmin -60 -exec ls -l {} \;
-rw-------  1 root root 1028 Jun 21 15:01 ./cron
-rw-------  1 root root 831752 Jun 21 15:42 ./secure

例10:僅僅在當前文件系統中搜索

系統管理員有時候僅僅想在/掛載的文件系統分區上搜索,而不想去搜索其他的掛載分區,比如/home/掛載分區。如果你有多個分區被掛載了,你想在/下搜索,一般可以按下面的這樣做

下面這個命令會搜索根目錄/及其子目錄下所有.log結尾的文件名。如果你有多個分區在/下面,那麼這個搜索會去搜索所有的被掛載的分區:

1
# find / -name "*.log"

如果我們使用-xdev選項,那麼僅僅會在在當前文件系統中搜索,下面是在xdev的man page上面找到的一段-xdev的定義:

  • -xdev Don’t descend directories on other filesystems.

下面的命令會在/目錄及其子目錄下搜索當前文件系統(也就是/掛載的文件系統)中所有以.log結尾的文件,也就是說如果你有多個分區掛載在/下面,下面的搜索不會去搜索其他的分區的(比如/home/)

1
# find / -xdev -name "*.log"

例11: 在同一個命令中使用多個{}

linux手冊說命令中只能使用一個{},不過你可以像下面這樣在同一個命令中使用多個{}

1
# find -name "*.txt" cp {} {}.bkup \;

注意,在同一個命令中使用這個{}是可以的,但是在不同的命令裏就不行了,也就是說,如果你想象下面這樣重命名文件是行不通的

1
find -name "*.txt" -exec mv {} `basename {} .htm`.html \;

例12: 使用多個{}實例

你可以像下面這樣寫一個shell腳本去模擬上面那個重命名的例子

1
# mv "$1" "`basename "$1" .htm`.html"

上面的雙引號是爲了防止文件名中出現的空格,不加的話會有問題。然後你把這個shell腳本保存爲mv.sh,你可以像下面這樣使用find命令了

1
find -name "*.html" -exec ./mv.sh '{}' \;

所以,任何情況下你在find命令執行中想使用同一個文件名多次的話,先寫一個腳本,然後在find中通過-exec執行這個腳本,把文件名參數傳遞進去就行,這是最簡單的辦法

例13: 將錯誤重定向到/dev/nul

重定向錯誤輸出一般不是什麼好的想法。一個有經驗的程序員懂得在終端顯示錯誤並及時修正它是很重要的。

尤其是在find命令中重定向錯誤不是個好的實踐。 但是如果你確實不想看到那些煩人的錯誤,想把錯誤都重定向到null設備中(也就是linux上的黑洞裝置,任何丟進去的東西消失的無影無蹤了)。你可以像下面這樣做

1
find -name "*.txt" 2>>/dev/null

有時候這是很有用的。比如,如果你想通過你自己的賬號在/目錄下查找所有的*.conf文件,你會得到很多很多的”Permission denied”的錯誤消息, 就像下面這樣:

1
2
3
4
5
6
7
8
9
10
11
12
13
$ find / -name "*.conf"
/sbin/generate-modprobe.conf
find: /tmp/orbit-root: Permission denied
find: /tmp/ssh-gccBMp5019: Permission denied
find: /tmp/keyring-5iqiGo: Permission denied
find: /var/log/httpd: Permission denied
find: /var/log/ppp: Permission denied
/boot/grub/grub.conf
find: /var/log/audit: Permission denied
find: /var/log/squid: Permission denied
find: /var/log/samba: Permission denied
find: /var/cache/alchemist/printconf.rpm/wm: Permission denied
[Note: There are two valid *.conf files burned in the "Permission denied" messages]
你說煩人不?所以,如果你只想看到find命令真實的查找結果而不是這些”Permission denied”錯誤消息,你可以將這些錯誤消息重定向到/dev/null中去
1
2
3
4
$ find / -name "*.conf" 2>>/dev/null
/sbin/generate-modprobe.conf
/boot/grub/grub.conf
[Note: All the "Permission denied" messages are not displayed]

例14: 將文件名中的空格換成下劃線

你從網上下載下來的音頻文件的文件名很多都帶有空格。但是帶有空格的文件名在linux(類Unix)系統裏面是很不好的。你可以使用find然後後面加上rename命令的替換功能去重命名這些文件,將空格轉換成下劃線

下面顯示怎樣將所有mp3文件的文件名中的空格換成_

1
$ find . -type f -iname “*.mp3″ -exec rename “s/ /_/g” {} \;

例15: 在find結果中同時執行兩條命令

在find的man page頁面中,下面是一次文件查找遍歷中使用兩條命令的語法舉例

下面的find命令的例子,遍歷文件系統一次,列出擁有setuid屬性的文件和目錄,寫入/root/suid.txt文件, 如果文件大小超過100M,將其記錄到/root/big.txt中

1
2
# find / <span class="MathJax_Preview">\( -perm -4000 -fprintf /root/suid.txt '%#m %u %p\n' \)</span><script type="math/tex"> -perm -4000 -fprintf /root/suid.txt '%#m %u %p\n' </script> , \
<span class="MathJax_Preview">\( -size +100M -fprintf /root/big.txt '%-10s %p\n' \)</span><script type="math/tex"> -size +100M -fprintf /root/big.txt '%-10s %p\n' </script>



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章