![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=1738835944-0L8GyrUcVOAYoO4MCdLuO9mnDoVDFEJW-0-c43f92228f599f4f37271be193e42975)
结果显示如下,可以看到year.c的绝对路径。
![](https://epubservercos.yuewen.com/7143D2/23083819001905006/epubprivate/OEBPS/Images/67_02.jpg?sign=1738835944-jdNNvo2aSrphzVGb1sIIJlpvBVCd5rgR-0-902efc65c2ba044a4e31b4057a4e2af0)
2.示例2:查找名字不确定的文件/目录
如果不确定查找对象的名字,例如记不清楚要查找的文件是year.c,只记得该文件是一个C语言代码文件,以c作为扩展名。那么可以使用通配符 * 进行查询匹配,示例如下。
![](https://epubservercos.yuewen.com/7143D2/23083819001905006/epubprivate/OEBPS/Images/67_03.jpg?sign=1738835944-fsJsvuER17rpq56iHRbQHWiJ97l29nYG-0-42dff2951f7f5e6f360e144618dab6d3)
结果会显示 /usr/share目录下所有以c为扩展名的文件的绝对路径,可以在结果中筛选出想要的结果。
![](https://epubservercos.yuewen.com/7143D2/23083819001905006/epubprivate/OEBPS/Images/67_04.jpg?sign=1738835944-n3qIG1bwqScHklBwW0d0S0sSQHaBY7vs-0-0465c404b91bde1a21a70fb75ce3c6f2)
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=1738835944-NfQhd0WrEPzvvpKGnF8fykmhpVL3bCDK-0-18f5ffc409df354eddcb2583615435f2)
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=1738835944-1RlOcz3Hc1lqYK86lXW2l46wcXY0q2Q4-0-6ba98ad1de1567f9d16c3ed51d32360c)
使用find将/etc/下所有扩展名为sh的文件复制到mysh目录,命令如下。
![](https://epubservercos.yuewen.com/7143D2/23083819001905006/epubprivate/OEBPS/Images/68_01.jpg?sign=1738835944-E6wcqlXrFnwosh3TACPc7Ab2LGpjhWW0-0-9f110758dee26dca958cf15a52d96681)
上述命令和参数说明如下。
● 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=1738835944-xCyfkOlpBDSn0dl2yMOUFYDV9UCk0jZV-0-f6629bf642057e19de40f8809ae90088)
5.示例5:命令组合(二)
本例使用find + -exec统计/etc下扩展名为sh的文件的代码行数,命令如下,wc用来统计文本文件中的行数,-l是选项,表示打印行数。
![](https://epubservercos.yuewen.com/7143D2/23083819001905006/epubprivate/OEBPS/Images/68_03.jpg?sign=1738835944-WahQvy69HstVZSK5beMRjacXf7g1iKTe-0-a5364a7a2f263d30ff6265aeeb8e0cc1)
也可以采用下面的命令。
![](https://epubservercos.yuewen.com/7143D2/23083819001905006/epubprivate/OEBPS/Images/68_04.jpg?sign=1738835944-TA8CbcVX3ffYYMpzXwoJIy2cHKBPMPQP-0-e4436d132e15e754d370c38792576516)
执行结果如下,会打印每个sh文件的行数。
![](https://epubservercos.yuewen.com/7143D2/23083819001905006/epubprivate/OEBPS/Images/68_05.jpg?sign=1738835944-BhPSbd9GbJyZ1mAT2lPwrM80LkkeGPCU-0-0dfb5177b0a974fc66ac35f972209949)
换一种实现方法,使用管道将find的输出(stdout)作为wc的输入,命令如下。
![](https://epubservercos.yuewen.com/7143D2/23083819001905006/epubprivate/OEBPS/Images/68_06.jpg?sign=1738835944-PVnZjy7BX0Qn95jub95jONTkcXK2EmoN-0-d4f1415a76f1256a2216adeb39a13a88)
执行结果是10,如下所示。
![](https://epubservercos.yuewen.com/7143D2/23083819001905006/epubprivate/OEBPS/Images/68_07.jpg?sign=1738835944-Rt04Zf4izma7DNSNX3nuMyMS8PuGHRgb-0-88ede550c7ef9bc95006f73e8470f5ed)
为什么输出结果不是每个文件的行数呢?这是因为,find的输出是一个整体,其中包含了10个sh文件的绝对路径,以此作为wc的输入(这个输入可以认为是一个文件,该文件包含了10条绝对路径),因此,wc的输出就是10。而在前面的-exec或$(find /etc/ -name "*.sh")中,find的输出被分解成了一个个的参数(共10个),wc会对每个参数进行处理,从而输出每个文件的行数。