去年猪厂内推机试中看到了关于find命令的考题,find命令还是很常用的,但无奈用法太丰富,一直记得不全,索性趁假日休息,汇总一下。
本文是4月的开胃小菜,也是第一次写命令的使用,有不恰之处,望指正。
命令格式
find [path] [expr]
path表示搜索的根路径,绝对路径和相对路径均可。expr则用于条件搜索,可以指定约束条件。
按文件名搜索
如果需要搜索指定形式的文件,例如所有txt文件,我们可以使用-name
选项指定文件名,这里可以接受通配符匹配,由于包含特殊字符,所以最好使用双引号括起来。
例:搜索所有png文件
find / -name "*.png"
# 忽略大小写
find / -iname "*.png"
如果需要将文件地完整路径作为匹配的对象,则可以使用-path
。
例:搜索img目录下的png文件
find / -path "*/img/*.png"
# 忽略大小写
find / -ipath "*/img/*.png"
如果想要使用更加精确的正则表达式,则可以通过-regex
选项进行匹配,它和-path
的类似,目标都是路径。
例:搜索png或jpg文件
find / -regex ".*\(\.jpg | \w+\.png\)$"
# 忽略大小写
find / -iregex ".*\(\.jpg | \w+\.png\)$"
按时间查找
Linux有3种类型的时间戳,分别是访问时间、修改时间和变化时间,相关细节不再复述。find支持根据指定的时间戳类型搜索对应时间范围内的文件。
find支持如下时间戳相关的参数:
-atime
:访问时间(单位:天)-mtime
:修改时间(单位:天)-ctime
:变化时间(单位:天)-amin
:访问时间(单位:分)-mmin
:修改时间(单位:分)-cmin
:变化时间(单位:分)
这些参数对应的值有如下形式:
- -N:小于N
- N:等于N
- +N:大于N
例:搜索2天内修改过的txt文件
find . -mtime -2 -name "*.txt"
按文件大小查找
通过-size
参数可以指定期望文件的大小,具体值的形式和上一节类似,除此之外,支持的单位如下:
- b:块(512B)
- c:字节(1B)
- w:字(2B)
- k:1024B
- M:1024KB
- G:1024MB
例:搜索全部大小在20KB之内的C源文件
find . -size -20k -name "*.c"
按文件类型查找
通过-type
参数可以确定待查找文件的文件类型,这个的类型和test中的类型缩写是一样的,如下是一个简单列表:
- f:普通文件
- l:符号链接
- d:目录
- c:字符设备
- b:块设备
- s:套接字
- p:管道
例:搜索/var目录下的所有套接字
find /var -type s
按权限查找
通过-perm
参数,我们可以在表达式内部制定目标文件的权限,该参数的值具备3种类型。
为了更好地说明,不妨令参数制定的权限位P,目标文件的权限位T,则
- P:精确匹配,P == T
- -N:子集关系,(P & T) == T
- /N:任何一个权限位匹配即可,(P & T) != 0
例:搜索当前用户可以修改的C源文件
find . -type f -perm -0600 -name "*.c"
除了8进制的权限值,也可使用o=w
之类的形式。
根据用户/组查找
通过-user
和-group
,可以限定期望文件的所属用户与组。
例:搜索所有属于users组的png文件
find / -type f -group users -name "*.png"
搜索深度
当文件量巨大时,搜索将变得十分耗时,如果你已经知道文件的深度,则可以通过如下参数进行约束:
-mindepth
:对不小于该深度的路径应用表达式-maxdepth
:对不大于该深度的路径应用表达式
例:搜索深度不大于3的目录中的所有png文件
find . -type f -maxdepth 3 -name "*.png"
表达式
上述的约束其实均为表达式的一个子式,find支持括号
、not
、or
、and
和,
,默认情况下所有的子式均采用and
的形式组成。
- ( expr )
- ! expr 亦可使用-not expr,不遵循POSIX
- expr -a expr 亦可使用expr -and expr,不遵循POSIX
- expr -o expr 亦可使用expr -or expr,不遵循POSIX
- expr , expr
逻辑表达式是支持短路的,可以做适当优化。
例:寻找所有png或jpg文件
find / -type f \( -name "*.png" -o -name "*.jpg" \)
表达式优化
和SQL一样,语义相同的find表达式,其执行效率可能完全不同。
一些建议:
- depth参数应该紧跟path,效果就如同“先做JOIN再select”和“先select再JOIN”
- type在depth之后
- type之后才是常见的约束项
其他
- 分隔符
find与xargs命令结合使用,通常会需要使用-print0,它指定'0'作为分隔符。默认情况下,搜索的结果使用'n'或者' '作为分隔符,此时如果文件名中包含空格,会就出现误操作的情况,因此需要指定一个名字中不可能出现的字符作为分隔符,最好的选择自然就是'0'了(当然不会是'/',这样的问题更大)。
- 执行指令
对于搜索结果我们可以通过增加额外的指令来执行对其进行的操作,默认的操作为-print
,即打印其路径。
除此之外,常见的还有-delete
和-exec
,前者的作用很明显,而后者则可执行自己定制的命令,如下:
例:将所有png文件转移到backup目录
find / -type f -name "*.png" -exec cp {} backup \;
其中{}表示文件名,;
则表示命令结束,-exec
只支持单条指令。
- 略过特定目录
如果我们需要在搜索时略过特定目录,可以使用-prune
。
例:打印除.config目录以外的所有文件路径
find . \( -name ".config" --prune \) -o \( -type f -print \)
-delete
和-prune
不能同时出现在表达式内,因为前者默认开启了-depth
,-depth
参数指明先处理目录的内容后处理目录本身,与-prune
冲突。