Linux find
命令用来在指定目录下查找文件。
find命令功能强大,选项比较多,能够记住的选项就那么几个,正好通过这次好好整理一下(不是全部,仅常用选项);查阅文档的时候对pathname前的几个选项一直不是很清楚,不知为何网上的帖子大都没有涉及到这部分,本篇参考了‘远有青山’的文章
用法:
#find [-H] [-L] [-P] [-Olevel] [-D debugopts] [path...] [expression]
通常情况下find命令使用忽略掉pathname
前的选项就可以
#find pathname -options [-print] [-exec -ok command] {} \;
其中-H -L -P
选项主要负责符号链接的处理:
- -H 表示只跟随命令行中指定的符号链接
- -L 表示跟随所有的符号链接
- -P 是默认的选项,表示不跟随任何符号链接,也就是说-P 选项可以不加
- -D 为调试选项,配合相关选项打印出调试信息;
- -O 针对查询顺序等因素,使用不同级别优化查询过程
E.g.
如果当前目录下有一个符号链接a123
,想在想要查找文件名最后一位是数字的文件,那么下面两种将不会显示a123
的结果:
#find . -name "*[0-9]" -print
#find -H . -name "*[0-9]" -print
如果需要找出符号链接a123
,可以这么写:
#find -H a123 . -name "*[0-9]" -print
#find -L . -name "*[0-9]" -print
find选项:
pathname
部分指定了使用者查询的原始路径,而且此路径和后续表达式一定要置于-D -H -L -P -O
这些选项的后边
命令中的[expression]是匹配项表达式。根据man手册提供的信息,表达式可分为三部分:
- option 设置项
- test 测试项
- action 动作项
三部分结合使用,就体现出了find命令的强大所在。
Option
设置项的一些选项针对此次查找任务,而不是针对文件进行配置,返回值总是True。
- -depth 查找文件时,先查找指定目录中的文件,而后查找其子目录。(Tests类中也有此选项,目前不太清楚怎么回事)
- -maxdepth 限定搜索目录的深度
- -mindepth 限定搜索目录的深度
- -follow 跟踪链接文件,找到原文件
- -mount 不跨越挂载点进行查找
- -version 打印版本号并退出
- -help 打印常规用法并退出
maxdepth/mindepth
限定查询深度:
- maxdepth 指最大不超过几层目录;[0,n]
- mindepth 指最小不超过几层目录;[n,无限深度]
规定当前目录为第一层深度。
在家目录下2层深度查找123:
#find /home/dshowing/ -maxdepth 2 -name 123
/home/dshowing/123
/home/dshowing/test/123
在家目录下3层深度查找123:
#find /home/dshowing/ -maxdepth 3 -name 123
/home/dshowing/123
/home/dshowing/test/123
/home/dshowing/test/abc/123
在家目录第二层和第三层目录之间查找123:
#find /home/dshowing/ -mindepth 2 -maxdepth 3 -name 123
/home/dshowing/test/123
/home/dshowing/test/abc/123
Tests
测试项是针对具体文件进行匹配测试,常见有-name -type
等选项,返回值为True或False。
- -name 按照文件名进行查找
- -perm 按照文件权限进行查找
- -prune 这一选项可以使find不在当前指定的目录中进行查找,如果同时出现
-depth
选项,此选项则被忽略 - -user 按照文件所属主进行查找
- -nouser 查找无有效属主的文件,即所属主不在
/etc/password
文件中 - -group 按照文件所属组进行查找
- -nogroup 查找无有效属组的文件,即所属组不在
/etc/groups
文件中 - -newer A !B 查找更改时间比文件
A
新但是比文件B
文件旧的文件 - -type 查找某一类型的文件,其中有:
- b 块设备文件
- d 目录
- c 字符设备文件
- p 管道文件
- l 符号链接文件
- f 普通文件
- -size n[c] 查找文件长度为n块的文件,带c时表示文件大小以字节计
- -mtime n/-n/+n 按照文件的更改时间进行匹配,
-n
表示更改时间距现在n天以内,+n
表示文件更改时间已经超过n天 - -atime n/-n/+n 参照文件被读取或执行的时间进行匹配
- -ctime n/-n/+n 参照文件状态被改变的时间进行匹配
- -depth 查找文件时,先查找当前目录的文件,再在其子目录中进行查找
- -mount 查找文件时,不跨越文件系统的挂载点
- -follow 如果查询时匹配到了链接文件,那么跟踪至所指向的原文件
- -cpio 对匹配的文件使用
cpio
命令,将这些文件备份到磁带设备中
-name
文件名匹配是使用次数最多的匹配方式,使用通配符匹配,查找小写字母开头数字结尾的TXT文件:
#find /opt/ -name "[a-z]*[0-9].txt" -print
-print
是缺省选项,可不加
-perm
按照文件权限进行匹配,通常使用8进制的权限表示法,别的我没试过,平常几乎不用。根目录查找仅属主有读权限的文件:
#find / -perm 400
-prune
如果在查找过程中希望忽略某个目录,那么可以使用-prune
选项来指定;但是如果在设置项中同时指定了-depth
选项,则此选项无效,将被忽略。
根目录下查找文件,跳过/home目录:
#find / "/home/" -prune -name -o -print
user/nouser
查找指定用户文件/无有效用户文件:
#find / -user nginx -print
#find / -nouser -print
group/nogroup
类似于user和nouser选项:
#find / -group workterm -print
#find / -nogroup -print
newer
如果能够确定两个文件的大体更改时间,并想查找处于这段时间内的文件,可以使用-newer
选项;其中!
为逻辑非符号,一般格式为:
find pathname -newer older_filename ! newer_filename -print
列出更改时间比older_filename
文件新,但比newer_filename
文件旧的文件:
#find /home/ -newer older_filename ! newer_filename -exec ls -lh {} \;
查找比123.log
文件新的(更改时间晚于123.log
)的文件:
#find /home/ -newer 123.log -exec ls -lh {} \;
mtime/ctime/atime
三种时间针对文件或目录的三种不同的时间属性:
- mtime (modify time)文件内容更改时间
- ctime (change time)文件状态更改时间
- atime (access time)文件被读取或执行的时间
选项参数中的n指的是n*24h,需要注意的是对时间范围的界定:
-
find . -mtime n
指的是更改时间距今n24小时至(n+1)24小时,包含n24小时;[n24h,(n+1)*24h) -
find . -mtime +n
指定是更改时间距今(n+1)24小时甚至更早; [(n+1)24h,正无穷) -
find . -mtime -n
指定是文件更改发生在n24小时以内; [0,n24h)
type
Unix和Linux系统中有多种文件类型,查找家目录中所有目录:
#find /home/dshowing/ -type d -print
查找当前目录中非目录文件:
#find . ! -type d -print
size
size选项按照文件长度(大小)进行匹配。
使用-size n/+n/-n [bcwkMG]
来限定文件的大小:
- b 单位为块,512字节为一块(缺省,不加单位时默认为块大小)
- c 字节大小
- w 字大小,1字=2字节
- k 千字节,kB
- M 兆字节,MB
- G 千兆字节,GB
1Byte=8bit
depth
使用此选项,现在指定目录中查找,而后再在其子目录中进行查找。先查找根目录,而后在子目录中查找:
#find / -name "123.txt" -depth -print
mount
仅在当前文件系统中查找,而不跨越到挂载点的其他系统文件:
#find . -name "123.txt" -mount -print
cpio
使用cpio选项可以在查找文件时将文件备份到磁带设备中,或将其恢复;平时几乎不使用,不做深究。
Action
动作选项决定对查找的文件作出具体操作。
- -delete 删除文件
- -print 在新行中,将查询结果显示在标准输出中
- -printf [format] 格式化输出,显示到标准输出
- \a 响铃
- \b 空格
- \n 回车换行
- \t 打印制表符
- -exec 执行命令操作
- -ok 分布执行命令操作
执行命令的一般格式为:-exec 'command' {} \;
,注意花括号后的空格
查找家目录中,文件大小大于100M,更改时间超过5天的文件,删除之:
#find /home/dshowing/ -size +100M -mtime +5 -exec rm -r {} \;
不建议在查找命令中直接使用删除操作,先确认再删除,减少心脏病发病的风险
如果非要这样,不如使用-ok 'command' {} \;
命令,相比于exec,它对文件的每一次执行都会在命令行中交互,每一步都需要确认:
#find / -size +100M -mtime +5 -ok rm -r {} \;
xargs和find
在find命令查找完成后,如果需要执行一些操作的时候,系统会限制传给-exec
选项的命令长度,如果命令参数过长,执行途中会报溢出错误。此时就可以用xargs
命令:
find /home/dshowing/ -size +100M -mtime +5 | xargs rm -rf
此外,使用find命令查找完成后,还可以使用管道符传送给之后的执行命令,这根使用xargs有些区别:
# pwd
/root/
# echo 123456 > test.txt
# find . -name *.txt
./test.txt
# find . -name *.txt | cat
./test.txt
# find . -name *.txt | xargs cat
123456
对于两种不同的输出,网友给出的解释是:
管道是实现:将前面的标准输出作为后面的标准输入;
xargs是实现:将前面的标准输出作为后一条命令的参数
牛平举了个“一切皆文件”的例子,感觉很形象:
# echo --help | cat
--help
# echo --help | xargs cat
Usage: cat [OPTION]... [FILE]...
Concatenate FILE(s), or standard input, to standard output.
...
...
...
Examples:
cat f - g Output f's contents, then standard input, then g's contents.
cat Copy standard input to standard output.
..
..
第一次,将--help
赋给了管道符,而后cat命令显示管道符内容;
第二次通过xargs,将--help
从管道符中读取出来,作为了cat命令的直接参数,输出的也就是help文档了。
More info: Click