前言
近期项目中要使用到find命令,下面两个点彻底搞蒙了我:
- -prune 参数怎么用
- -a -o 两个参数的短路逻辑如何理解
忽略指定目录
先说下如何忽略目录,有两种方式:
- ! -path “xxx”
- -path xxx -prune
1. 使用!- path
➜ tmpdir pwd
/tmp/tmpdir
➜ tmpdir tree #要查找的文件列表
.
├── dir1
│ ├── d1file1.txt
│ └── d1file2.txt
├── dir2
│ └── d2file2.md
└── file1
2 directories, 4 files
➜ tmpdir find /tmp/tmpdir -type f #查找所有的文件
/tmp/tmpdir/dir2/d2file2.md
/tmp/tmpdir/file1
/tmp/tmpdir/dir1/d1file2.txt
/tmp/tmpdir/dir1/d1file1.txt
➜ tmpdir find /tmp/tmpdir ! -path "/tmp/tmpdir/dir1*" -type f #忽略dir1目录
/tmp/tmpdir/dir2/d2file2.md
/tmp/tmpdir/file1
➜ tmpdir find /tmp/tmpdir ! -path "/tmp/tmpdir/dir1*" ! -path "/tmp/tmpdir/dir2*" -type f #忽略dir1和dir2目录
/tmp/tmpdir/file1
简单解释下,这里查找类型为文件的file,然后使用 ! -path 参数避开了dir1、dir2目录,这里的path 后面的参数必须带引号,而且因为是忽略目录,实际上是按照绝对路径的字符串来匹配,然后忽略的,所以这里的匹配需要在路径后面添加 * 通配符。
2. 使用 -prune 参数
➜ tmpdir pwd
/tmp/tmpdir
➜ tmpdir tree
.
├── dir1
│ ├── d1file1.txt
│ └── d1file2.txt
├── dir2
│ └── d2file2.md
└── file1
2 directories, 4 files
➜ tmpdir find /tmp/tmpdir -path /tmp/tmpdir/dir1 -prune -o -type f -print #忽略dir1
/tmp/tmpdir/dir2/d2file2.md
/tmp/tmpdir/file1
➜ tmpdir find /tmp/tmpdir -path /tmp/tmpdir/dir1 -prune -o -path /tmp/tmpdir/dir2 -prune -o -type f -print #忽略dir1和dir2
/tmp/tmpdir/file1
先使用 -prune 参数忽略了 dir1 目录,然后使用忽略了 dir1 和 dir2 两个目录,因为使用了 -prune 参数,所以末尾需要使用 -print 参数,同时这里还使用了 -o 参数,下面来解释。
-a 和 -o 的短路逻辑
先来一条命令举个例子:
find /tmp/tmpdir -path /tmp/tmpdir/dir1 -prune -o \
-path /tmp/tmpdir/dir2 -prune -o \
-type f -print
实际上是把忽略dir1和dir2的命令切分成了三行。
-a 是条件与,-o 是条件或,所以 -o 前面的满足之后,后面的就不会再执行。
也就是说遇上了 dir1 路径,就会执行 -prune 忽略该路径,所以就不会再继续,只有发现当前查找的路径不是 dir1 时,才会继续 -o 后面的判断,判断是不是 dir2 路径,不是就继续判断 -o 后面的,从而查到了非dir1和非dir2的文件列表。
这里比较容易混淆,因为用的是 -o ,但是按照人的思维,这里要得效果是 既不是 dir1 又不是 dir2,所以感觉是 与 的关系,但是正是因为使用到了短路逻辑,所以达到了预期的效果。
再来看一个既包含 -o 又包含 -a 的:
➜ tmpdir find /tmp/tmpdir -path /tmp/tmpdir/dir1 -prune -o -type f -print #查找非 dir1 下的文件
/tmp/tmpdir/dir2/d2file2.md
/tmp/tmpdir/file1
➜ tmpdir find /tmp/tmpdir -path /tmp/tmpdir/dir1 -prune -o -type f -a -name 'file1' -print #查找非 dir1 且文件名是file1
/tmp/tmpdir/file1
拆分上面的命令就是:
find /tmp/tmpdir -path /tmp/tmpdir/dir1 -prune -o\ #或关系
-type f -a\ #与关系
-name 'file1' -print
解释上面就是:
是dir1目录就排除,然后短路不执行
不是才继续判断是否是文件,不是则短路,是则继续判判断
文件名是不是 file1 , 是则查找成功。
哈哈~