find:文件查找命令

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

你可能感兴趣的:(find:文件查找命令)