首頁 > php教程 > PHP开发 > 主體

Find命令實戰

高洛峰
發布: 2016-12-14 17:28:30
原創
1422 人瀏覽過

話說linux中我最常用的幾個指令就是awk, grep, vim, find,今天我們就來詳細看下find指令的使用 

先來一個簡單例子: 

Shelloo . 表示查找路徑為目前目錄(你也可以指定為其他工程目錄,譬如:~/workspace/login) 

-name 表示搜尋的目標檔名或目錄名(允許使用shell通配符) 


通常上述指令已經能夠完成日常工作需求的80%,但是要想完成另外的20%,你必須再深入了解下find指令... 

現在假設你需要找Test.java 和TEST.java這兩份文件,這時候你該如何做? 
也許你會find . -name "Test.java" 和 find . -name "TEST.java" 執行兩遍 

雖然這樣做結果正確,但是有沒有更簡單的方式呢? 答案,自然有 


Shell程式碼 

find . -name "*.java"  # 递归查找当前目录下所有java文件
登入後複製

發現沒,是不是更優雅了... 

現在我們更進一步,假設我們需要列出~/scripts目錄下所有名為study的文件該如何做呢?


在不了解find命令之前,也許你需要使用shell for循環來遞歸遍歷目錄,然後對每個找到的study判斷是否為文件(有可能是名為study的目錄),若確實是文件則輸出.說了這麼多,這個方式真的是繁瑣異常,但是如果你了解find指令,那麼just one line! 


Shell程式碼 

find . -iname "test.java"   # -iname 与-name参数含义一样,但是忽略大小写
登入後複製

其中-type參數用來指定搜尋的目標類型,f表示普通文件, -type還有其他常用的參數值:f-檔, d-目錄 

現在你已經了解了: 

1.如何指定find搜尋路徑 
2.如何指定find搜尋的目標類型(-type) 
3.要如何指定find搜尋的檔案名稱或目錄名稱(-name / -iname) 

真是不少東西了呢,不過我們要繼續前行,find指令還有很多很有用的參數。

find命令預設是遞歸搜索,它的搜尋演算法應該是我們常說的深度優先遍歷(可以透過指定-depth參數指定採用廣度優先遍歷演算法),但是有時候我們希望僅在當前目錄搜索,或是能夠指定遞迴查找的深度,這時候該如何做呢? 兩個字簡單 

-maxdepth: 指定遞歸查找時的目錄最大深度,若為1,表示僅在當前目錄查找 
-mindepth: 指定遞歸查找時的目錄最小深度 

現在我們看兩個例子(先不要嘗試去運行): 


Shell代碼 

find ~/scripts -type f -name "study"
登入後複製

這兩個命令看似沒有什麼差異,但是運行效果確相差萬裡(特別是當文件很多目錄又非常深時),或者在有的機器上第一種形式根本無法運行,原因為什麼呢? 

因為第一個命令它首先會找出所有java文件,然後再篩選出滿足深度條件的文件,這樣效率非常非常之低,而第二個命令則只是在1-3層目錄下搜尋目標文件,而沒有對整個文件樹進行遞歸遍歷,所以效率很高. 


在我的機器上執行第一種命令,彈出以下警告: 
find: warning: you have specified the -maxdepth option after a non-option argument -name, but options are not positional (-maxdepth affects tests specified before it as well as those specified after tests specified before it as well as those specified after tests). ,你現在你的手上又多了兩把利器-maxdepth 和-mindepth(這個兩個參數,可以提高你的查找效率以及zhuangbility) 

find命令還幾個很有用的參數 
-mtime: 文件內容最後修改時間 
-atime: 檔案最後存取時間 
-ctime: 檔案meta資訊最後修改時間(譬如檔案權限) 

這幾個參數後面要跟一個整數值使用,eg: 

如果你需要查找某個時間段內的修改的文件,這些命令就非常有效了(搞運維的同學應該經常使用) 

說了這麼多參數(-name, -iname, -type, -mindepth , -maxdepth, -mtime等等),想必你對find命令已經有所了解, 
現在我們來看看find命令的一個好基友----xargs 

通常我們需要對查找出來的文件執行某些action,譬如我想查找某個工程目錄下所有使用到StringUtils的java文件,這時候該怎麼辦呢? 

方法1我們可以使用eclipse的搜索,方法2我們可以寫腳本,方法3 just one line ... 



Shell程式碼 

find ~/worksapce/project -name "*.java" | xargs grep "StringUtils"
登入後複製

其中:
find ~/worksapce/project -name "*.java" 将会在家目录下workspace/project中递归查找所有java文件
xargs grep "StringUtils" 表示在文件中(find命令查找出的结果集)查找含有StringUtils字样的文件

也许有人一开始会这样写:find ~/worksapce/project -name "*.java" | grep "StringUtils"
这个命令执行将不会产生任何结果,而原因就是因为没有使用xargs!

现在我们就来说说xargs:xargs是用来把输入流转化为参数的命令(默认把输入流中的空白字符譬如"\n"(换行)替换成" "(空格))

Shell代码

$ cat test   
a  
b  
c  
d  
e  
$ cat test | xargs  
a b c d e
登入後複製

ind命令将查找出的每一个文件名或目录名默认用"\n"分割,然后通过管道 | 作为输入流传递给grep命令,但是grep命令要求输入流必须是参数的形式,譬如:grep "target" file1 file2 所以必须使用xargs重新将输入流转换为参数

说到这里,一些比较严谨的同学也许会说,这样的命令:find ~/worksapce/project -name "*.java" | grep "StringUtils" 是不严谨,不安全的(这里还谈不上不安全,毕竟只是一个grep命令,但要是变成xargs rm -rf 那就危险了),原因就是find命令默认用"\n"分隔结果列表,而xargs会把"\n"转化成空格,所以当文件路径或者文件名含有"\n"这些字符时,就会被错误替换,这时候你在执行个rm -rf ,哦, 卖糕的...

所以我们应该养成好习惯,这样写

Shell代码

find ~/worksapce/project -name "*.java" -print0 | xargs -0 grep "StringUtils"
登入後複製

print0用'\0'(空字符)分隔结果列表,xargs -0 只会将'\0' 替换成空格,这样就不会出现刚才所说的问题了.... 


关于find命令,我就说到这里,赶紧尝试吧... 

更多Find命令实战相关文章请关注PHP中文网!

相關標籤:
來源:php.cn
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
最新問題
熱門推薦
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板