![Linux快速入门与实战:基础知识、容器与容器编排、大数据系统运维](https://wfqqreader-1252317822.image.myqcloud.com/cover/769/43806769/b_43806769.jpg)
2.3.6 Linux下的搜索神器——find
本小节介绍Linux下的搜索神器find命令,find功能强大且使用非常频繁,如果能够很好地使用find命令,将大大提升Linux下的工作效率。本小节将通过多个示例来介绍find的典型用法。
1.示例1:查找名字确定的文件/目录
假设用户要查找文件year.c,仅知道该文件位于 /usr/local目录下,但具体位于哪个子目录下不清楚。因此,需要使用find命令,来确定year.c的完整路径,具体命令如下,/usr/share是要查找的路径,-name指定查找对象的名字,即year.c。注意命令、选项和参数之间都要有空格。
![](https://epubservercos.yuewen.com/7143D2/23083819001905006/epubprivate/OEBPS/Images/67_01.jpg?sign=1739300278-tVtdtxogpBASvLodvAuiT0nodmdTPZSB-0-f35a24da2e209589145492496299a394)
结果显示如下,可以看到year.c的绝对路径。
![](https://epubservercos.yuewen.com/7143D2/23083819001905006/epubprivate/OEBPS/Images/67_02.jpg?sign=1739300278-DUUaelNd0Ykzwo8AILX24vkai3FC4ZEU-0-4c4cd4c00df4e871323a0ba080ab13ea)
2.示例2:查找名字不确定的文件/目录
如果不确定查找对象的名字,例如记不清楚要查找的文件是year.c,只记得该文件是一个C语言代码文件,以c作为扩展名。那么可以使用通配符 * 进行查询匹配,示例如下。
![](https://epubservercos.yuewen.com/7143D2/23083819001905006/epubprivate/OEBPS/Images/67_03.jpg?sign=1739300278-Db1zNGBxKLWWjf2kj3nl2nTOE4Mt6Efd-0-2e6ef7a74fb98745fbc7e62ffaafdf8c)
结果会显示 /usr/share目录下所有以c为扩展名的文件的绝对路径,可以在结果中筛选出想要的结果。
![](https://epubservercos.yuewen.com/7143D2/23083819001905006/epubprivate/OEBPS/Images/67_04.jpg?sign=1739300278-Canf8WwJV7lukJQsMJU39GB3G4ykxbvh-0-c893cacc1418b2a695c5ad868401d815)
find支持通配符,其中*表示任意字符串,?表示单个字符。
find也支持范围表示,例如使用[a-z]可以表示从a~z的单个字符,[0-9]表示从0~9的单个数字。
3.示例3:按照类型查找的文件/目录
-type选项可以实现按文件类型查找,例如查找 /dev/ 目录下所有的块设备文件,命令如下,其中-type指定文件类型,b表示块设备文件,注意-type和b之间有空格。
![](https://epubservercos.yuewen.com/7143D2/23083819001905006/epubprivate/OEBPS/Images/67_05.jpg?sign=1739300278-rezAPs4MNzofMN5f7sTI36331nJf0TwP-0-9f8ed0f459ab3f7dccf0db8e5251c7b2)
find后面要跟查找路径/dev/,-type b不能放到/dev/的前面。
如果不需要进行文件名的匹配,可以省略-name"*"。
文件类型中,b表示块设备文件,c表示字符设备文件,d表示directory,p表示命名管道,f表示普通文件,l表示符号链接/软链接,s表示套接字文件,D表示door类型文件(Solaris)。
4.示例4:命令组合(一)
-exec选项可以将查找命令和其他命令结合起来,对查找的结果做二次处理。例如将/etc/下所有的sh文件复制到当前目录mysh下,步骤说明如下。
创建目录mysh,命令如下。
![](https://epubservercos.yuewen.com/7143D2/23083819001905006/epubprivate/OEBPS/Images/67_06.jpg?sign=1739300278-ITOSVJp13kdf03jclqrwIzZojizdwYmX-0-61dafcf39e715cce59c64fb31810cd99)
使用find将/etc/下所有扩展名为sh的文件复制到mysh目录,命令如下。
![](https://epubservercos.yuewen.com/7143D2/23083819001905006/epubprivate/OEBPS/Images/68_01.jpg?sign=1739300278-AJ1D4ZNNR7bR8I9cGbkVlQ1BkTiYR1E4-0-8757dda75ea1cc45d08f64665d5417fe)
上述命令和参数说明如下。
● find/etc/-name"*.sh"表示查找/etc/目录下所有扩展名为sh的文件。
● -exec指定处理find结果的命令为cp。
● {}表示find的搜索结果,即sh文件的绝对路径将作为cp的源文件参数。
● mysh是cp的目的路径。
● \; 中的\是一个转义字符,它告诉bash不要再把 ; 当作分隔符处理,而是当作一个普通的字符,那么,此时 ; 就是一个普通的字符,它将作为exec的最后一个参数,即结束标识。如果不加 \,那么 ; 会被bash当成特殊符号(即语句的分隔符)进行处理,而不会作为exec的参数。因此,不管-exec后面连接的是什么命令,最后都要以 \; 结尾。
也可以用另外一种方式实现以上示例的功能,命令如下,其中$(find /etc/ -name "*.sh")会将find的结果转换成cp命令的输入参数。
![](https://epubservercos.yuewen.com/7143D2/23083819001905006/epubprivate/OEBPS/Images/68_02.jpg?sign=1739300278-3Y6ASC85eK46ZBaPKXd5JpkAtBa7Sk55-0-f141c3f1340d169349e1b151abe3b946)
5.示例5:命令组合(二)
本例使用find + -exec统计/etc下扩展名为sh的文件的代码行数,命令如下,wc用来统计文本文件中的行数,-l是选项,表示打印行数。
![](https://epubservercos.yuewen.com/7143D2/23083819001905006/epubprivate/OEBPS/Images/68_03.jpg?sign=1739300278-HgEtLKJ7FxkPwXlST34wjs8Z5eCFygs9-0-f169dd7a2c34fd13d45d1a2e354ef120)
也可以采用下面的命令。
![](https://epubservercos.yuewen.com/7143D2/23083819001905006/epubprivate/OEBPS/Images/68_04.jpg?sign=1739300278-fdi6uKGxUJf1a3WdWuqxeos7cr4zqCFm-0-a275ca048540f9a05cff446ceeb49b28)
执行结果如下,会打印每个sh文件的行数。
![](https://epubservercos.yuewen.com/7143D2/23083819001905006/epubprivate/OEBPS/Images/68_05.jpg?sign=1739300278-RcWRBSgSA8ysCmJ6hMmkqNWX7mFbREal-0-4d557a292773e217d4a4f255db21081a)
换一种实现方法,使用管道将find的输出(stdout)作为wc的输入,命令如下。
![](https://epubservercos.yuewen.com/7143D2/23083819001905006/epubprivate/OEBPS/Images/68_06.jpg?sign=1739300278-olmRwfyrQ3a4WY2A175hwgknZLl31Mo2-0-018f79feec47364559a29229f9695900)
执行结果是10,如下所示。
![](https://epubservercos.yuewen.com/7143D2/23083819001905006/epubprivate/OEBPS/Images/68_07.jpg?sign=1739300278-Rnf4Y4Wyveg3IbQHUwfFLoj3OKfgojYz-0-8d3e81985041f3ef1cd27e7fd99e80ea)
为什么输出结果不是每个文件的行数呢?这是因为,find的输出是一个整体,其中包含了10个sh文件的绝对路径,以此作为wc的输入(这个输入可以认为是一个文件,该文件包含了10条绝对路径),因此,wc的输出就是10。而在前面的-exec或$(find /etc/ -name "*.sh")中,find的输出被分解成了一个个的参数(共10个),wc会对每个参数进行处理,从而输出每个文件的行数。