如果没有提供除了 -prune 之外的其他 action 类型表达式,find 默认会加上 -print 表达式,并用 -and 来连接前面的表达式 。
这个行为可能会带来一些误解,认为 find 命令总是会打印搜索到、或者匹配到的文件名,但有时候搜索到、或者匹配到的文件名反而不打印 。
例如上面 find . -path ./tests -o -print 的例子 。
要消除这个误解,就一定要清楚地认识到,find 命令想要打印文件名,就必须执行到 -print 表达式、或者其他可以打印文件名的表达式 。
即,要执行可以打印文件名的表达式才会打印文件名,否则不会打印 。
至于是匹配特定模式的文件名会打印,还是不匹配特定模式的文件名才会打印,取决于各个表达式、包括操作符组合表达式的判断结果,看是否会执行到可以打印文件名的表达式 。
总结结合上面的说明,对 find . -path ./tests -and -prune -o -print 命令在查找时能够忽略 ./tests 目录底下文件的原因总结如下:
- find . 指定查找当前目录、及其子目录下的所有文件,每查找到一个文件名,就把这个文件名传递到后面的表达式进行评估,进行相应处理 。
- -path ./tests 指定传递下来的文件名要完全匹配 ./tests 这个字符串 。对于不匹配的文件名,该表达式返回 false,那么 -path ./tests -and -prune 这个组合表达式会返回 false,且没有评估后面的 -prune 表达式 。由于 -and 操作符优先级高于 -o 操作符,该组合表达式再跟后面的 -o -print 形成新的组合表达式,它返回 false,会往下执行 -print 表达式,从而打印出来不匹配的文件名 。
- 对于匹配 -path ./tests 模式的目录名,该表达式返回 true,-path ./tests -and -prune 组合表达式会评估后面的 -prune 表达式,指定不进入匹配的目录名查找底下的文件,这个例子里面就是不进入 ./tests 目录,所以查找时会忽略该目录底下的文件,但还是会查找到 ./tests 目录名自身 。
- 对于 ./tests 这个目录名,由于 -prune 返回 true,-path ./tests -and -prune 组合表达式会返回 true,基于 -o 操作符的特性,不执行后面的 -print 表达式,所以没有打印这个目录名 。
- 最后的 -o -print 是必要的,如果不加这两个参数,将不会打印不匹配 ./tests 模式的文件名 。
- 基于这几条分析,这个命令最终打印的结果里面,即不包含 ./tests 这个目录名,也不包含它底下的文件名 。
理解了上面对该命令的说明后,想要忽略其他模式的目录,应该就比较容易了 。
忽略多个目录的写法如果想要忽略多个目录,要使用 -o 操作符把多个 -path pattern 表达式组合起来 。
基于上面例子的目录结构,举例如下:
$ find . ( -path ./tests -o -path ./src ) -prune -o -print../Makefile.am
可以看到,find . ( -path ./tests -o -path ./src ) -prune -o -print 命令打印的查找结果里面,没有 ./src、./tests 这两个目录、及其底下文件,也就是忽略了这两个目录 。基于 -o 操作符的特性,-path ./tests -o -path ./src 组合表达式在不匹配 ./tests 模式时,会再尝试匹配 ./src 模式,两个模式都不匹配,才会返回 false 。
由于 -and 操作符优先级高于 -o 操作符,所以要用小括号 () 把 -path ./tests -o -path ./src 组合表达式括起来,形成一个独立的表达式,再跟后面的 -prune 组合成新的表达式 。
小括号在 bash 中有特殊含义,所以要加转义字符,写成 (,避免 bash 对小括号进行特殊处理 。
注意:在 ( 和 ) 前后要用空格隔开,这两个是单独的操作符,如果不加空格,会组合成其他名称 。
其他表达式的含义和作用可以参考前面例子的说明 。
如果能够基于这个命令的各个表达式、各个操作符的作用,推导出打印结果,就基本理解 find 命令的工作原理了 。
匹配特定模式的文件名上面说明的 -path pattern 表达式要求完全匹配整个目录路径,如果想要只匹配文件名,不包含目录路径部分,可以使用 -name pattern 表达式 。
这是一个 test 类型表达式,GNU find 在线帮助手册对该表达式的说明如下:
Test: -name pattern
True if the base of the file name (the path with the leading directories removed) matches shell pattern pattern. As an example, to find Texinfo source files in /usr/local/doc:
find /usr/local/doc -name '*.texi'
Notice that the wildcard must be enclosed in quotes in order to protect it from expansion by the shell.
推荐阅读
- ping 域名+端口 Windows和Linux下检测网络是否可用
- 10个实用Linux运维命令
- 在Centos7上安装图形化桌面工具
- 穿衣搭配|化妆师上「高级淡妆」的常用技巧,五星定妆法不怕卡粉、脱妆
- 防晒衣怎么选?教你3个小技巧,买到真正有防晒效果的防晒衣
- 绞股蓝最佳喝的时间,教你九个喝茶的技巧
- 玉兰花茶的泡法,玫瑰花茶泡法技巧
- Linux技巧:awk 命令简单入门介绍
- 如何做网络推广?有哪些渠道和方法?互联网老司机分享推广技巧
- 宫灯长寿花养殖方法及养护技巧