Linux find命令搜索技巧,掌握了,事半功倍
find命令是我们日常工作中常用的Linux命令。全面掌握这个命令,在很多操作中都可以达到事半功倍的效果。如果您对find命令有以下疑问,本文可以帮助您解决:
- find命令的格式是什么?
- 参数中的+或-符号是什么意思?例如,find / -mtime +7 和 find / -mtime -7 有什么区别?
- find /etc/ -name “passwd” -exec echo {} \; 和有什么区别并找到 /etc/ -name “passwd” -exec echo {} +?
- -为什么exec参数以“\;”结尾而不仅仅是“;”?
命令基础知识
find命令大家都知道,但是用独特的方式解释它是比较困难的。那我们不妨就照常做吧。我们一般使用的find命令的格式很简单,一般分为三部分:
find /etc -name 'passwd'格式如上,第一部分是find命令。第二段是要寻求的路径。该部分可以写多个目录,例如:
find /etc /var /usr -name 'passwd'第三部分是一个表达式。在我们的示例中,使用了表达式-name“passwd”,指定条件是查找文件名为passwd的文件。了解 find 命令最重要的是表达式部分。表达式指定搜索的文件应包含哪些属性。它还可以指定一些“动作”,例如删除满足某些条件的文件。 find命令的核心是表达式指定方法(EXPRESSION)。
find 命令中有四种类型的表达式,分别是:
- 测试:这是我们最常用的指定文件搜索的条件。
- 操作:可以对找到的文件执行的操作。
- 全局选项:全局属性用于限制一些搜索条件,例如常见的目录层次深度限制。
- Positional Options:位置属性用于指定一些搜索位置条件。
其中最重要的是测试和操作,它们是 find 命令的核心。此外,还有可以组合多个表达式的运算符。它们可以表达多个表达式之间的逻辑关系和运算优先级,称为运算符。
我们来看看这几个类别的功能。
测试
find 命令使用文件属性搜索文件。所以查找表达式测试都是文件属性条件,例如不同的文件时间、文件权限等。很多参数都会指定数字n,一般会有三种表示方法:
+n:表示大于n。
-n:表示小于n。
n:表示等于n .
按时间搜索
数值方法中指定的比较常用的参数是基于时间的搜索,如-mtime n:搜索文件修改时间,单位为天,即n*24小时。例如:
[root@zorrozou-pc0 zorro]# find / -mtime 7 -ls为了更方便地查看结果,我们在此命令中使用 -ls 参数。具体细节稍后会详细解释。现在我们需要知道的是,这个参数可以显示符合条件的文件的相关属性。然后我们就可以使用这个命令来查看找到的文件的修改时间。
[root@zorrozou-pc0 zorro]# find / -mtime 7 -ls|head
524295 4 drwxr-xr-x 12 root root 4096 6月 8 13:43 /root/.config
524423 4 drwxr-xr-x 2 root root 4096 6月 8 13:43 /root/.config/yelp
524299 4 drwxr-xr-x 2 root root 4096 6月 8 13:23 /root/.config/dconf
524427 4 -rw-r--r-- 1 root root 3040 6月 8 13:23 /root/.config/dconf/user
...我们发现时间以6月8日为中心,今天是:
[root@zorrozou-pc0 zorro]# date
2016年 06月 15日 星期三 14:30:09 CST事实上,如果我们为mtime输入7,我们实际上从现在起找到了24小时前的日期7修改的文件。如果我们注重细节的话,我们可以使用这个命令对找到的文件按照时间进行排序:
[root@zorrozou-pc0 zorro]# find / -mtime 7 -exec ls -tld {} \+这个命令使用了exec参数,稍后会详细解释。我们发现,找到的文件实际上集中在6月7日14:30到6月8日14:30之间。这意味着指定 7 天实际上意味着查找时间范围在当前时间 7.24 小时到 8.24 小时之间的文件。这就是不带+-号的7的含义。如果 -mtime 为 -7 会怎样?
[root@zorrozou-pc0 zorro]# find / -mtime -7 -exec ls -tld {} \+你会发现找到的文件都是从现在到7点24小时内的文件,但是不包括7点24小时到8点24小时的时间范围。那么-mtime +7 应该就很容易理解了。这意味着通过输入时间来查找。类似的参数包括:
-ctime:按修改时间(天)搜索文件。
-atime:按访问时间(以天为单位)查找文件。
-mmin:按修改时间(分钟)搜索文件。
-amine:按访问时间(以分钟为单位)查找文件。
-cmin:按修改时间(以分钟为单位)查找文件。
这些参数都指定了一个时间数字n,该数字的含义与mtime完全相同,只是时间单位和搜索时间不同。
find除了指定时间外,还可以通过比较相关文件时间来查找符合条件的文件,例如-anewer file。
[root@zorrozou-pc0 zorro]# find /etc -anewer /etc/passwd这样就可以找到/etc/目录下所有访问时间比/etc/passwd访问时间新的文件。类似的参数还有:
-cnewer:文件更改时间比较。
-较新:比较文件修改时间。
-newer 还有一个特殊的用途,可以用来比较不同的时间。比如我想查找文件修改时间比/etc/passwd文件修改时间新的文件:
[root@zorrozou-pc0 zorro]# find /etc/ -newermc /etc/passwd这种用法的原型是:find file /etc/ -newerXY.其中,Y表示与后续文件比较的时间,X表示与搜索文件比较的时间。 -newermc 比较文件更改时间和文件更改时间。可用于 X 和 Y 的字母是:
a:文件访问时间。
c:文件更改时间。
m:文件编辑时间。
在某些支持文件创建时间记录的文件系统上,可以使用B 来表示文件创建时间。 ext系列文件系统本次不支持上传。
按用户搜索
-uid n:文件所属用户uid为n。
-username:文件所属用户为name。
-gid n:文件组gid为n。
-组名:组为name的文件。
-nogroup:没有文件属于该组。
-nouser:没有属于该用户的文件。
根据权限查找
-可执行:文件可执行。
-可读:文件可读。
-可写:文件可写。
-perm模式:搜索具有模式权限的文件。模式可以写为数字或 ugo=rwx,例如:
[root@zorrozou-pc0 zorro]# find /etc/ -perm 644 -ls。这种写法相当于:
[root@zorrozou-pc0 zorro]# find /etc/ -perm u=rw,g=r,o=r -ls。
另请注意,该模式指定完全符合此权限的文件。例如:
[root@zorrozou-pc0 zorro]# find /etc/ -perm u=rw,g=r -ls
263562 4 -rw-r----- 1 root brlapi 33 11月 13 2015 /etc/brlapi.key未描述的权限相当于指定不存在该权限。
模式也可以用 / 或 - 作为前缀来描述。如果指定了-mode,则表示忽略未指定的权限。这意味着权限必须仅包含适当的权限。例如:
[root@zorrozou-pc0 zorro]# find /etc/ -perm 600 -ls这是查找所有只有rw权限的文件——-而-600表示是否包含其他有rw权限的文件。mode加/前缀表示指定的权限只需要某一位来构成条件,其他位作为-忽略。这意味着-perm /600也可以找到像r————或-w————这样的权限的文档。旧版本的/前缀用+表示,但新版本的搜索概念不支持模式前的+前缀。
查找模式
-按路径命名:文件名是具有由模式指定的字符串的文件。请注意,如果模式包含*等特殊符号,则必须添加“”。
-name:名称的不区分大小写版本。
-pattern lname:查找符号链接文件名为pattern的文件。
-ilname:lname 的不区分大小写的版本。
-pathpattern:根据完整路径查找名为pattern的文件,如:
[root@zorrozou-pc0 zorro]# find /etc -path '/e*d'| head
/etc/machine-id
/etc/profile.d
/etc/vnc/xstartup.old
/etc/vnc/config.d
/etc/vnc/updateid
/etc/.updated-ipath:不区分大小写的路径版本。
-正则表达式模式:将文件名与正则表达式匹配。
-iregex:正则表达式的不区分大小写的版本。
寻找另一种状态
-空:文件为空,是普通文件或目录。
-size n[cwbkMG]:输入文件长度来搜索文件。单位选择位:
c:单位字节。
b:单位是块,块大小为512字节,这是默认单位。
w:字代表两个字节。
k:以1024字节为单位。
M:以1048576字节为单位。
G:温度单位(1073741824 字节)。数字名称
n 前面也可以带有 +- 符号。含义与时间类似,表示找到小于指定长度(-)的文件或大于指定长度(+)的文件。
-inum:按文件 inode 号搜索。
-links n:按文件连接数搜索。
-samefile name:查找与name指定的文件完全相同的文件,这意味着两个文件紧密相连。
-type c:按文件类型查找文件:
c 可选择的类型有:
b:块设备
c:字符设备
d:目录
d:目录命名管道
f:普通文件
l:符号链接
s:抽屉
ACTIONS
表达式中的操作类型参数主要是用于处理文件的参数。在上面的例子中,我们看到-ls参数可以用来以长格式显示找到的文件,这是一个action类型的参数。类似的参数也有。
-fls file:与-ls功能相同,不同的是信息写入file指定的文件中,而不是显示在屏幕上。
-打印:在屏幕上显示找到的文件。事实上,默认的 find 命令会打印文件并显示它们。
-print0:-print参数将每个文件换行分割,该参数适用于零分割。有时可以在脚本编程中使用它。
-fprint 文件:-print 参数的写入文件版本。将内容写入文件而不是将其显示在屏幕上。
-fprint0 文件:用于写入-print0 的文件版本。
-删除:可以直接删除找到的文件。
-printf:以格式化输出模式打印。例如:
[root@zorrozou-pc0 zorro]# find /etc/ -name 'pass*' -printf '%p '
/etc/default/passwd /etc/pam.d/passwd /etc/passwd- /etc/passwd
将显示由空格分隔的文件名。 %p代表文件名。更多信息可以在 man find 中找到。
-prune:如果复合条件是目录,则不搜索该目录。示例:
[root@zorrozou-pc0 zorro]# mkdir /etc/passs
[root@zorrozou-pc0 zorro]# touch /etc/passs/passwd
[root@zorrozou-pc0 zorro]# find /etc/ -name 'pass*' -prune
/etc/passs
/etc/default/passwd
/etc/pam.d/passwd
/etc/passwd-
/etc/passwd
[root@zorrozou-pc0 zorro]# find /etc/ -name 'pass*'
/etc/passs
/etc/passs/passwd
/etc/default/passwd
/etc/pam.d/passwd
/etc/passwd-
/etc/passwd首先我们创建了目录 /etc/pass,然后在该目录中创建了一个名为 passwd 的文件。然后用find加上-prune可以看到pass目录可以显示出来,但是目录下的passwd文件没有显示出来,说明这个参数阻止find进入该目录并搜索。然后find不带-prune参数会在pass目录下显示passwd。
-quit:找到符合条件的文件后立即退出。
执行命令
-exec
find命令。 find命令的exec参数是一个非常有用的参数。当然,它造成的损害也可能非常大。在学习这个之前,我想提醒大家,在使用之前需要先确定自己在做什么。
此参数的常用格式为:
-exec command ;注意末尾的分号。它用于表示查找。 find 解析命令时,必须区分给定的参数是传递给自身还是传递给命令。因此,Find 使用分号作为要执行的命令的所有参数的结束标记。如果命令的返回值为0,则返回true。在exec参数指定的运行命令中,可以使用{}符号来表示当前find查找到的文件名。例如:
[root@zorrozou-pc0 find]# find /etc/ -name 'passwd' -exec echo {} \;
/etc/default/passwd
/etc/pam.d/passwd
/etc/passwd上面的命令的意思是在/etc/目录下找到一个名为passwd的文件,并重复它的名字。注意,使用分号时,必须在其前面添加转换字符\。由于分号也是 bash 特殊字符,因此 bash 会首先解释它。在其前面添加一个\可以让bash直接将其正文输入到find命令中。这个分号是由 find 解释的,而不是由 bash 解释的。事实上,这个exec是比较没有意义的。毕竟,find 本身会找到符合适当条件的文件并显示其名称。但想象一下,如果我们替换 echo rm 或 cp,不是更有意义吗?例如:
[root@zorrozou-pc0 find]# find /etc/ -name 'passwd' -exec rm {} \;请不要执行此命令! !
或者:
[root@zorrozou-pc0 find]# find /etc/ -name 'passwd' -exec cp {} {}.bak \;该命令可以为所有符合条件的文件添加.bak 扩展名,并创建备份副本。这样我们就可以进行删除了:
[root@zorrozou-pc0 find]# find /etc/ -name 'passwd.bak'
/etc/default/passwd.bak
/etc/pam.d/passwd.bak
/etc/passwd.bak
[root@zorrozou-pc0 find]# find /etc/ -name 'passwd.bak' -exec rm {} \;
[root@zorrozou-pc0 find]# find /etc/ -name 'passwd.bak'
当然你在删除之前还是要确认你要删除的文件一定是正确的。
-execdir
execdir 和 exec 之间存在一些差异,特别是在执行指定命令时,各自的命令将在哪个工作目录中执行。 exec是find中指定的起始目录,execdir是文件所在的目录。对比之后你就会明白:
[root@zorrozou-pc0 find]# find /etc/ -name 'passwd' -exec echo {} \;
/etc/default/passwd
/etc/pam.d/passwd
/etc/passwd
[root@zorrozou-pc0 find]# find /etc/ -name 'passwd' -execdir echo {} \;
./passwd
./passwd
./passwd第一个命令打印的路径都是以/etc/开头,第二个命令打印的路径都是当前目录下的具体文件。
execdir 方法比 exec 更安全,因为这种执行方法避免了解析文件名时发生的冲突。
除了上面两种典型的命令执行方式外,find还为这两个参数提供了另一种命令执行格式:
-exec command {} +
-execdir command {} +
首先看这种格式和分号结束方式的区别参见示例:
[root@zorrozou-pc0 find]# find /etc/ -name 'passwd' -exec echo {} \;
/etc/default/passwd
/etc/pam.d/passwd
/etc/passwd
[root@zorrozou-pc0 find]# find /etc/ -name 'passwd' -exec echo {} \+
/etc/default/passwd /etc/pam.d/passwd /etc/passwd光是这样看可能不太明显。我们可以这样描述它们的执行过程:
echo /etc/default/passwd
echo /etc/pam.d/passwd
echo /etc/passwd和
echo /etc/default/passwd /etc/pam.d/passwd /etc/passwd实际上对于命令 {} 来说意味着; format,每次找到文件就执行对应的命令,而{}+format命令则表示先执行find,查找所有符合条件的文件。然后将每个文件作为命令参数传递给命令来执行。 exec 给出的命令实际上只执行一次。这种用法的局限性很明显:{} 只能出现一次。
[root@zorrozou-pc0 find]# find /etc -mtime -7 -type f -exec cp -t /tmp/back/ {} \+上面的命令会将所有符合条件的文件传输到/tmp/back目录下。如果文件具有相同的名称,它们当然会被覆盖。从这个命令我们将了解到使用{}+格式的安全注意事项。不能写成:
find /etc -mtime -7 -type f -exec cp {} /tmp/back/ \+,所以只能使用-t参数改变cp命令参数的顺序来指定相关动作。
无论如何,直接使用 exec 和 execdir 都是危险的,因为它们会直接对找到的文件调用适当的命令,而无需任何确认。因此,我们在进行相关操作之前需要再三确认,防止滥用。当然,find还提供了更安全的exec参数,它们是:
-ok
-okdir
它们的功能与exec和execdir相同。唯一的区别是,在执行任何操作之前,都会要求用户进行确认。没关系?例如:
[root@zorrozou-pc0 find]# find /etc -mtime -7 -type f -ok cp -t /tmp/back/ {} \;
< cp ... /etc/bluetooth/main.conf > ?
所以每次CP的时候都要确认是否要这样做。如果您键入 y 或以 y 开头的任何字符串,则会提交。其他字符串将被拒绝。另外,这两个参数不支持{}+格式。
运算符
Find 的运算符(OPERATORS)实际上是用来链接多个表达式并确定它们的逻辑关系。例如:
[root@zorrozou-pc0 zorro]# find /etc -name 'pass*' -type f
/etc/passs/passwd
/etc/default/passwd
/etc/pam.d/passwd
/etc/passwd-
/etc/passwd此查找命令使用两个表达式,它们之间没有任何分隔。这实际上意味着查找满足这两个条件的文件。其实就是逻辑关系的AND表达式,与合取-and参数或-and参数相同:
[root@zorrozou-pc0 zorro]# find /etc -name 'pass*' -a -type f
/etc/passs/passwd
/etc/default/passwd
/etc/pam.d/passwd
/etc/passwd-
/etc/passwd
[root@zorrozou-pc0 zorro]# find /etc -name 'pass*' -and -type f
/etc/passs/passwd
/etc/default/passwd
/etc/pam.d/passwd
/etc/passwd-
/etc/passwd除了逻辑AND关系外,还有逻辑OR关系:
[root@zorrozou-pc0 zorro]# find /etc -name 'pass*' -o -type f
[root@zorrozou-pc0 zorro]# find /etc -name 'pass*' -or -type f表示如果满足两个条件之一,那就可以了。
添加!在条件表达式之前对表达式进行否定。同样的方法也可以与 -not 参数一起使用。另外,如果表达式较多,可以使用(expr)来指定优先级,例如:
[root@zorrozou-pc0 zorro]# find / \( -name 'passwd' -a -type f \) -o \( -name 'shadow' -a -type f \)这意味着:-name "passwd" -a -type f 和 -name "shadow" -a -type f 分别是或关系。
最后还有一些在
find中可以常用的参数,比如:
-深度:制定这个参数后,遇到目录时,首先进入该目录来处理该目录中的文件目录并最终为目录本身提供服务。
-maxdepth:最大目录深度限制。
-mindepth:最小目录深度限制。
还有一些其他相关参数大家可以在man find中自己添加,这里就不多废话了。 来自公众号:Linux系统技术作者:邹立伟
版权声明
本文仅代表作者观点,不代表Code前端网立场。
本文系作者Code前端网发表,如需转载,请注明页面地址。
code前端网