linux_find命令

非原创,仅收集整理自用。侵权即删,谢谢

更详细说明,可以man find 和 info find。

一、Get Start

查找当前目录下的所有文件:

find .

find命令的一般格式:

find [-H] [-L] [-P] [path...] [expression]

find [-H] [-L] [-P] [-D debugopts] [-Olevel] [path...] [expression]

-H 只跟随命令行中指定的symbol link

-L 跟随所有的symbol link

-P 默认选项,不跟随symbol link

例如,在当前目录下有一个符号链接e1000,第一种写法找不出该文件,第二种写法可以。

find -H . -name "*[0-9].c" -print

./2234.c

find -H e1000 . -name "*[0-9].c" -print

./2234.c
./e1000

[path...]是要检索的路径。

[expression]分成三类:设置项 option,测试项 test,动作项 action。

设置项如-depth,-maxdepth

测试项如-name,-user,-regex,-wholename,-path,-size,-perm,-type

动作项如-print,-prune,-exec

二、以-name检索

当前目录及子目录中查找name以一个大写字母开头或者小写a或b开头的文件:

find . -name "[A-Za-b]*" -print

./a_book_of_c.chm
./TMP1234

双引号中是shell通配符用法,不是正则表达式。这里务必区分开。

https://www.jianshu.com/p/25f3d0cd5fdc
Shell中的通配符

-name对大小写字母敏感,如果想匹配时不考虑大小写,可以使用-iname测试项。

'i'可以加在许多选项前面,比如-ipath, -iregex, -iwholename等,都表示大小写不敏感。

三、以正则表达式检索

-regex同样属于测试项。使用时注意-regex匹配完整的文件名(包括路径)。

find /var/log -type f -regex ".*\-[0-9]+" -o -regex ".*\.log\.[0-9]"

/var/log/cron-20210715
/var/log/secure-20210725
/var/log/audit/audit.log.1

还有一个设置项 '-regextype',可以依喜好选择正则表达式的类型。

-regextype Currently-implemented types are emacs (this is the default), posix-awk, posix-basic, posix-egrep and posix-extended.

四、以wholename与path检索

-wholename和-path都属于测试项,而且功能一样。

-path字面上给人一种错觉,好像只匹配路径名,其实它也可以匹配文件名。因此-wholename这个名字更贴切。

find . -path '*phone/pu*'

./phone/puk.txt

五、逻辑运算符

按照优先级从高到底:

(expr)
! expr
-not expr 同上,但是POSIX不支持
expr1 expr2 与运算。先对expr1求值,若为false,则不对expr2求值
expr1 -a expr2 同上
expr1 -and expr2 同上,但是POSIX不支持
expr1 -o expr2 或运算。先对expr1求值,若为true,则不对expr2求值
expr1 -or expr2 同上,但是POSIX不支持
expr1 , expr2 逗号表达式。都会求值,但只返回expr2的值,expr1的值丢弃

理解find命令的搜索规则(也可以说find命令的算法):

find命令递归遍历所指定的目录树,针对每个文件依次执行find命令中的表达式,表达式首先根据逻辑运算符进行结合,然后依次从左至右对表达式求值。以下面代码为例,进行说明。

find PATHP1 OPT1 TEST1 ACT1 ( TEST2 or TEST3 ) ACT2

(1) 根据OPT1设置项进行find命令的整体设置,若没有-depth设置项,依次进行下面的步骤

(2) 令文件变量File = PATHP1

(3) 对File文件进行TEST1测试,若执行结果为false,转(8)

(4) 对File文件进行ACT1动作,若执行结果为false,转(8)

(5) 对File文件进行TEST2测试,若执行结果为true,转(7)

(6) 对File文件进行TEST3测试,若执行结果为false,转(8)

(7) 对File文件进行ACT2动作

(8) 若File文件是一个目录,并且没有被执行过-prune动作,则进入此目录

(9) 当前目录下是否还有文件,若有依次取一个文件,令File指向此文件,转(3);

(10) 判断当前目录是否是PATHP1,若是则程序退出;若不是,则返回上一层目录,转(9)

-----------------------------------

找当前目录下,文件名中包括字母'e',在'e'之后又有数字的不是目录文件的所有文件:

find . -name "*e*[0-9]*" ! -type d -print

解释一下它在做什么:

find . -size +0c -wholename "*e*[0-9]*" -o ! \( -name "." -o -name "*phone" \) -prune -name "*.c" -user xixi -o -name "*phone"

六、-prune

-prune是一个动作项。表示当文件是一个目录文件时,不进入此目录进行搜索。

find . -prune

.
find . -size +4090c -print

.
./a_book_of_c.chm

find . -size +4096c -print

./a_book_of_c.chm
find . -size +4090c -prune

.

find . -size +4096c -prune

./a_book_of_c.chm

注意:如果同时使用-depth设置项,那么-prune将被find命令忽略。

-prune True; if the file is a directory, do not descend into it. If -depth is given, false; no effect. Because -delete implies -depth, youcannot usefully use -prune and -delete together.

说到这里,又得说说-depth设置项。man手册页中如是说:"-depth Process each directory's contents before the directory itself."。这有点像树的后序遍历,先遍历当前节点的所有子节点,然后再访问当前节点。从find结果中打印先后顺序能看出。

七、时间戳

文件有三个时间属性:创建时间、最近修改时间、最近访问时间。

最近修改时间又包括两种,一是文件的状态(也即权限如rwx等)最近被修改时间,一是文件的数据(也即内容)最近被修改时间。touch命令改变的即是文件数据最近被修改时间。

最近访问时间,指的是最近一次文件数据(内容)被访问的时间。因此,使用ls命令输出文件的相关信息并不会修改文件的最近访问时间。

find命令提供了针对文件的最近访问时间、文件状态最近被修改时间、文件数据最近被修改时间进行匹配的测试项,分别是-amin, -cmin, -mmin和-atime, -ctime, -mtime两组,第一组基于分钟,第二组基于天。

以-amin为例,假设当前时间tnow="2007-11-12 14:42:10"、t1="2007-11-12 14:39:10"、t2="2007-11-12 14:40:10",那么要查找最近访问时间属于[t1,t2]时间段的文件,可以这么写:

find . -amin 3

若测试项参数是数字,则基本上都可以在数字参数前加"+"或者"-"号,表示“大于”或“小于”的意思,因此,要查找最近访问时间属于[t1,tnow]时间段的文件,可以这么写:

find . -amin -3

"-amin n"

1、求Δt,用当前时间减去文件对应属性的时间值即得到Δt,Δt = tnow - tfile;

2、求浮点数f,用Δt除以1分钟,f = Δt / 1min;

3、将f的小数部分入到整数部分,得到n。即,不管f是6.0102还是6.8901,n都等于7

"-atime n"

1、求Δt,用当前时间减去文件对应属性的时间值即得到Δt,Δt = tnow - tfile;

2、求浮点数f,用Δt处以24小时,f = Δt / 24hours;

3、将f的小数部分都舍掉,得到n。即,不管f是6.0102还是6.8901,n都等于6

#查找并删除当前目录下七天前的以.txt结尾的文件,不查找当前目录下的子目录

find ./ -maxdepth 1 -type f -name "*.txt" -mtime +7 -exec rm -rf {} \;

八、权限位-perm

权限位测试项:-perm。-perm支持符号权限位表示法也支持绝对(八进制)权限位表示法。

-perm基本上有下面这几中形式:

-perm mode File's permission bits are exactly mode.

-perm -mode All of the permission bits mode are set for the file.

-perm /mode Any of the permission bits mode are set for the file.

-perm +mode (此形式已经不推荐使用,功能与/mode相同)

#查找主目录下所有的后缀名为.txt .pdf .rm并且具有可执行权限位的文件

find ~ \( -name "*.txt" -o -name "*.pdf" -o -name "*.rm" \) \
-not \( -type d -o -type l \) \
-perm /111 -print

九、文件类型

-type c
File is of type c:
b block (buffered) special
c character (unbuffered) special
d directory
p named pipe (FIFO)
f regular file
l symbolic link; this is never true if the -L option or the -follow option is in effect, unless the symbolic link is broken.
If you want to search for symbolic links when -L is in effect, use -xtype.
s socket

-xtype c
The same as -type unless the file is a symbolic link.

共7种文件类型。

十、文件大小

默认情况下以块计量文件大小,若想使用字节来计量只需要在数字参数后加c即可。

-size n[cwbkMG]
File uses n units of space. The following suffixes can be used:
`b' for 512-byte blocks (this is the default if no suffix is used)
`c' for bytes
`w' for two-byte words
`k' for Kilobytes (units of 1024 bytes)
`M' for Megabytes (units of 1048576 bytes)
`G' for Gigabytes (units of 1073741824 bytes)

The size does not count indirect blocks, but it does count blocks in sparse files that are not actually allocated. Bear in mind that the `%k' and `%b' format specifiers of -printf handle sparse files differently. The `b' suffix always denotes 512-byte blocks and never 1 Kilobyte blocks, which is different to the behaviour of -ls.

十一、用户和用户组

-uid n
-user username or uid
-nouser
-gid n
-group gname or gid
-nogroup

十二、输出格式

如果你不想查找到你想要的文件时单调的输出文件名,你可以使用-printf动作项输出你想要的格式,下面举几个-printf动作的参数:

%p 输出文件名,包括路径名

%f 输出文件名,不包括路径名

%m 以8进制方式输出文件的权限

%g 输出文件所属的组

%h 输出文件所在的目录名

%u 输出文件的属主名

...

find . -user xixi -printf "%m %p \\n"

644 ./phone1/hello.c
644 ./0dfe.c
find /var/log -mtime +1 -a -size +100M -o -name "*.log" -printf %u' '%g' '%s' '%AT' '%Ax' '%M' '%p'\n'

root root 6243 11:36:34.4110000020 05/31/2021 -rw-r--r-- /var/log/boot.log
root root 9098 08:49:25.6299999620 11/20/2020 -rw------- /var/log/yum.log
find ./ -mtime +1 -a -size +100M -o -name "*.log" -exec ls -lh {} \;

-rw-r--r-- 1 root root 6.1K May 31 11:36 ./boot.log
-rw------- 1 root root 8.9K Jun 30 15:58 ./yum.log

十三、执行外部命令

find对查找到的文件能调用外部命令进行处理。-exec动作项就是来完成这个功能的,格式是:

find . EXPR1 -exec command {} \;
注意:后一个花括号'}'和'\'之间有一个空格。

例如,查找当前目录下的所有普通文件,并用ls命令输出:

find . -type f -exec ls {} \;

有些操作系统中出于安全考虑只允许-exec选项执行诸如ls或ls -l这样的命令。

也可以使用-exec动作项的安全模式:-ok动作项。它的功能和语法都跟-exec一样,只不过它以更安全的模式运行,当要删除文件时,它会给出提示,让你选择到底删除还是不删。

例如:

find . -name "*abc*" -ok rm {} \;

使用-exec动作项处理匹配到的文件时,find命令会将所有匹配到的文件"一起"传递给exec执行。

但有些系统对能够传递给exec的命令长度有限制,这样在find命令运行几分钟之后,就会出现溢出错误。错误信息通常是“参数列太长”或“参数列溢出”。这就是xargs命令的用处所在,特别是与find 命令一起使用。

xargs的使用格式是:

find PATH EXPR1 EXPR2 | xargs command

利用管道,把find命令匹配到的文件名传递给xargs命令,而xargs命令每次只获取一部分文件而不是全部。这样它可以先处理最先获取的一部分文件,然后是下一批,并如此继续下去。

在有些系统中,使用-exec动作项会为处理每一个匹配到的文件而发起一个相应的进程,并非将匹配到的文件全部作为参数一次执行;这样在有些情况下就会出现 进程过多,系统性能下降的问题,因而效率不高;而使用xargs命令则只有一个进程。

另外,在使用xargs命令时,究竟是一次获取所有的参数,还是分批取得参数,以及每一次获取参数的数目都会根据该命令的选项及系统内核中相应的可调参数来确定。

例如,要在普通文件中查找文件内容中包含"io"的文件:

find . -type f | xargs grep -ir io

Binary file ./a_book_of_c.chm matches
./2234.c:#include <stdio.h>
./3e10.c:#include <stdio.h>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值