Linux命令分享第一天之find命令

发布于:2023-01-11 ⋅ 阅读:(504) ⋅ 点赞:(0)

1.find-复杂的文件查找方法

find命令可以根据各种属性在指定目录(及其子目录)中查找文件,find有很多值得关注的特性。
find命令最简单的用法就是为其指定一个或多个目录作为查找范围,find命令的美妙之处在于能够找出符合特定条件的文件,这是通过运用各种选项(options)、测试条件(test)以及操作(action)来实现的。

[root@lvs /]# find ~
/root
/root/.bash_logout
/root/.bash_profile
/root/.bashrc
/root/.cshrc
/root/.tcshrc
/root/anaconda-ks.cfg
/root/.bash_history
/root/.viminfo

1.1 测试条件

  1. 查找根目录下的所有目录并统计目录数量
    [root@lvs ~]# find / -type d |wc -l
    13751  
    
  2. 查找根目录下的所有文件并统计文件数量
    [root@lvs ~]# find / -type f |wc -l
    93243
    

3.列出find命令支持的常见文件类型

  • b 快设备文件
  • c 字符设备文件
  • d 目录
  • f 普通文件
  • l 符合链接
  1. 还可以加入其他测试条件,按找文件大小和文件名查找,查找所有匹配通配符模式*.log且大于1MB的普通文件

    [root@lvs ~]# find / -type f -name "*.log" -size +1M |wc -l
    1
    

    注意:将通配符放入双引号中是为了避免Shell对其进行路径名扩展。-size +1M表示查找的文件大于1M;如果是-size -1M表示查找的文件小于1M,如果是-size 1M表示与指定值完全相等。M表示计量单位是MB,常用的计量单位k(KB),M(MB),G(GB)

  2. 常见的测试条件

    测试条件 描述
    -cmin n 匹配n分钟前内容或属性发生变化的文件或目录,如果不足n分钟,使用-n;如果超过n分钟,就用+n
    -cnewer file 匹配内容或属性发生变化时间比file更晚的文件或目录
    -ctime n 匹配内容或属性在n*24小时之前发生变化的文件或目录
    -empty 匹配空文件或目录
    -group name 匹配属于组name的文件或目录,name可以使用组名或者数值显示的组ID来表示
    -iname pattern 类似于-name,但是忽略大小写
    -inum n 匹配i节点号为n的文件,有助于找出特定i节点的所有硬链接
    -mmin n 匹配内容在n分钟之前发生变化的文件或目录
    -mtime n 匹配内容在n*24小时之前发生变化的文件或目录
    -name pattern 匹配符合制定通配符模式pattern的文件或目录
    -newer file 匹配内容发生变化的时间比file更晚的文件或目录,在编写执行文件备份的Shell脚本时,该测试条件非常有用
    -nouser 匹配不属于合法用户的文件或目录,该测试条件用于查找已删除用户的文件或是监测攻击者的活动
    -nogroup 匹配不属于合法组的文件或目录
    -perm mode 匹配指定权限mode的文件或目录,mode可以使用八进制或符号表示法表示
    -size n 匹配大小为n的文件
    -type c 匹配类型为c的文件
    -user name 匹配属于用户name的文件或目录,name可以使用用户名或用户ID表示

1.2 操作符

通过逻辑操作符组合多个测试条件,表达更为复杂的逻辑关系。

1.查找目录中权限不为0600的文件和权限不为0700的目录
[root@ansible /]# find ~ \( -type f -not -perm 0600 \) -or \( -type d -not -perm 0700 \)

find命令的操作符

操作符 描述
-and 操作符两侧的测试结果均为真,则匹配。操作符可以简写为-a。注意,如果没有在命令行中写明操作符,默认假定为-and
-or 只要操作符任意一侧的测试结果为真,则匹配。该操作符可以简写为-o
-not 如果操作符后的测试结果为假,则匹配。该操作符可以简写为!
() 对测试条件和操作符分组,能够形成更大的表达式,该操作符可用于控制逻辑求值的优先级。默认情况,find命令的求值顺序是从左到右,常见的作法是使用反斜杠来转义括号。

上面表达换一种写法是

[root@ansible /]# find ~ \( -type f -not -perm 0600 \) -or \( -type d -not -perm 0700 \)
因为-and是默认使用的,所以将其排除。之后就得到了下面的命令
[root@ansible /]# find ~ \( -type f -not -perm 0600 \) -or \( -type d -not -perm 0700 \)

1.3 预定义操作

得到find命令的查找结果固然有用,但我们真正想做的是对结果执行某些操作。幸运的是,find命令允许这么做。除了一些已经预定义号的操作,也可以应用用户的自定义操作。先看下find命令预定义的操作。

操作符 描述
-delete 删除当前匹配的文件
-ls 对匹配的文件执行相当于ls-dils命令的操作,输出结果结果被发送至标准输出。
-print 将匹配文件的完整路径名输出至标准输出
-quit 一旦发现匹配就退出
1.查找用户主目录(及其子目录)中的所有文件,查找扩展名为.bak的文件,找到之后,将其删除。
[root@ansible ~]# find ~ -type f -name '*.bak' -delete

使用-delete操作时,一定要格外小心,在实际删除文件之前,先使用-print代替-delete,确认查找结果无误。

1.4 用户自定义操作

除了预定义操作,还可以针对查找结果调用任意命令,传统的实现方式是使用-exec操作,用法如下:

-exec command {} ;


这里command是命令名。{}是代表当前路径名的符号。;作为分隔符,表示命令结束。下面演示删除操作

-exec rm ‘{}’ ‘;’

因为{}和;对Shell具有特殊含义,所以必须对其进行标注或转义。

1.5 提高效率

当使用-exec时,每找到一个匹配文件,就会执行一次指定的命令,效率较低。我们更希望所有的查找结果合并在一起,执行一次命令。

ls -l file1 file2 file3
而不是
ls -l file1
ls -l file2
ls -l file3

这样一来,命令只需要执行一次,而不是多次。这有两种实现方法:传统方式和现代方式,前者使用xargs,后者使用find命令的自身新特性。将尾号的分号改为加号,就能让find命令将查找结果组合成参数列表,供指定的命令一次性使用。见下例:

[root@ansible glob]# find ~ -type f -name 'foo*' -exec ls -l '{}' ';'
-rw-r--r-- 1 root root 0 Aug 19 18:07 /root/foo.txt
-rw-r--r-- 1 root root 0 Aug 19 18:08 /root/glob/foo

[root@ansible glob]# find ~ -type f -name 'foo*' -exec ls -l '{}' +
-rw-r--r-- 1 root root 0 Aug 19 18:07 /root/foo.txt
-rw-r--r-- 1 root root 0 Aug 19 18:08 /root/glob/foo

结果没变化,但系统只执行了一次ls命令。

1.6 xargs

xargs命令的功能很有意思,它从标准输入接收输入,将其转换为指定命令的参数列表。

[root@ansible glob]# find ~ -type f -name 'foo*' -print |xargs ls -l
-rw-r--r-- 1 root root 0 Aug 19 18:07 /root/foo.txt

find命令的输出结果通过管道传给了xargs命令,后者构造出ls命令的参数列表,然后执行该命令。

1.7 实战演练

1.先部署一个实验环境,创建100目录和100个文件
[root@ansible ~]# mkdir -p playground/dir-{001..100}
[root@ansible ~]# touch playground/dir-{001..100}/file-{A..Z}
2.执行find命令查找file-A文件并打印
[root@ansible ~]# find playground -type f -name 'file-A' -print
3.统计file-A的数量
[root@ansible ~]# find playground -type f -name 'file-A' -print |wc -l

接下来,演示如何根据文件的修改时间进行查找,这在创建备份文件或按时间顺序组织文件时能派上用场。

1.创建一个用于比较修改时间的参照文件
[root@ansible ~]# touch playground/timestamp
[root@ansible ~]# stat playground/timestamp
  File: ‘playground/timestamp’
  Size: 0               Blocks: 0          IO Block: 4096   regular empty file
Device: fd00h/64768d    Inode: 33989673    Links: 1
Access: (0644/-rw-r--r--)  Uid: (    0/    root)   Gid: (    0/    root)
Access: 2022-08-19 21:08:10.566534805 +0800
Modify: 2022-08-19 21:08:10.566534805 +0800
Change: 2022-08-19 21:08:10.566534805 +0800
 Birth: -
[root@ansible ~]#
2.再次使用touch命令,然后执行stat命令,发现文件的时间更新了
[root@ansible ~]# touch playground/timestamp
[root@ansible ~]# stat playground/timestamp
  File: ‘playground/timestamp’
  Size: 0               Blocks: 0          IO Block: 4096   regular empty file
Device: fd00h/64768d    Inode: 33989673    Links: 1
Access: (0644/-rw-r--r--)  Uid: (    0/    root)   Gid: (    0/    root)
Access: 2022-08-19 21:09:43.374538124 +0800
Modify: 2022-08-19 21:09:43.374538124 +0800
Change: 2022-08-19 21:09:43.374538124 +0800
3.使用find命令更新部分文件
[root@ansible ~]# find playground -type f -name 'file-B' -exec touch '{}' ';'
4.将playgroud目录下的所有文件与timestamp比对,识别出已更新的文件
[root@ansible ~]# find playground -type f -newer playground/timestamp

1.8 find命令选项

最后要讲的是可用于控制find命令 查找范围的选项,在构建find表达式时,这些选项可与其他测试条件和操作共同使用。

操作符 描述
-depth find命令在处理目录本身之前先处理该目录中的文件,如果指定了-delete操作,则自动应用此选项。
-maxdepth levels 设置find命令在执行和操作时,向下深入的最大目录层级。
-mindepth levels 设置find命令在执行和操作时,向下深入的最小目录层级。
-mount 要求find命令不遍历挂载在其他文件系统上的目录

网站公告

今日签到

点亮在社区的每一天
去签到