***Linux文件查找命令find***

时间:2022-11-17 09:19:55

 前言:关于find命令

优劣对比常用的grep只能通过文本内容过滤(行)查找文件,而locate 数据库【依据/var/lib/mlocate内的数据库记载,找出使用者输入的关键字档名】查找却是模糊匹配,将指定的字符串跟整个路径进行匹配  -i 忽略大小写 -n N 只显示匹配到的前N个文件。而此时find命令则体现出其强大之处。

由于find具有强大的功能,所以它的选项也很多,其中大部分选项都值得我们花时间来了解一下。即使系统中含有网络文件系统( NFS),find命令【它是搜索硬盘来查找文件】在该文件系统中同样有效,只要你具有相应的权限。

 在运行一个非常消耗资源的find命令时,很多人都倾向于把它放在后台执行,因为遍历一个大的文件系统可能会花费很长的时间(这里是指30G字节以上的文件系统)。

一。find命令的一般形式为:

find [PATH] [option] [action]

二。find命令的参数:

pathname: find命令所查找的目录路径。例如用.来表示当前目录,用/来表示系统根目录
-print: find命令将匹配的文件输出到标准输出。
-exec: find命令对匹配的文件执行该参数所给出的shell命令。相应命令的形式为'command' {} \;,注意{}和\;之间的空格
-ok: 和-exec的作用相同,只不过以一种更为安全的模式来执行该参数所给出的shell命令,在执行每一个命令之前,都会给出提示,让用户来确定是否执行。

三。find命令选项:

1.与时间有关的选项,共有-atime,-ctime与-mtime【-atime表示的是访问时间;-ctime表示被改变文件状态的时间;-mtime表示被修改文件内容的时间】,以-mtime说明

     -mtime n:n为数字,意思是在n天之前的【一天之内】被更改过内容的文件;

     -mtime +n:列出在n天之前(不含n天本身)被更改过内容的文档名;

     -mtime -n:列出在n天之内(含n天本身)被更改过内容的文档名;

另外需要区别以下内容:

   -amin n
  查找系统中最后N分钟访问的文件

  -atime n
  查找系统中最后n*24小时访问的文件
  -cmin n
  查找系统中最后N分钟被改变文件状态的文件

  -ctime n
  查找系统中最后n*24小时被改变文件状态的文件
    -mmin n
  查找系统中最后N分钟被改变文件数据的文件

  -mtime n
  查找系统中最后n*24小时被改变文件数据的文件

如果我想要找出『4天内被更动过的文件档名』,那可以使用『find /var -mtime -4 』。那如果是『4天前的那一天』就用『find /var -mtime 4

***Linux文件查找命令find***

图中最右边为目前的时间,越往左边则代表越早之前的时间轴啦

  • +4代表大于等于5天前的档名: find /var -mtime +4
  • -4代表小于等于4天内的文件档名:find /var -mtime -4
  • 4则是代表4-5那一天的文件档名: find /var -mtime 4

范例一:将过去系统上面 24 小时内有更动过内容 (mtime) 的文件列出

[root@www ~]# find / -mtime 0
# 那个 0 是重点!0 代表目前的时间,所以,从现在开始到 24 小时前,也就是24小时之内
# 有变动过内容的文件都会被列出来!那如果是三天前的 24 小时内?
# find / -mtime 3 有变动过的文件都被列出的意思!

范例二:寻找 /etc 底下的文件,如果文件日期比 /etc/passwd 新就列出
[root@www ~]# find /etc -newer /etc/passwd
# -newer 用在分辨两个文件之间的新旧关系是很有用的!

#find -newer apache-maven-2.2.1-bin.tar.gz  ! -newer status.sh -ls【查找更改时间比文件apache-maven-2.2.1-bin.tar.gz新但比文件status.sh旧的文件

8393137    4 drwxr-xr-x   3 root     root         4096 Oct 18 15:19 .
8392815    4 -rw-r--r--   1 root     root          164 Oct 18 15:19 ./status.sh
8392814    4 -rw-r--r--   1 root     root          164 Oct 18 15:18 ./1
8196333 62300 -rwxr-xr-x   1 root     root     63724381 Jun 30 17:51 ./jdk-6u5-linux-x64.bin
8393838 24388 -rw-r--r--   1 root     root     24942637 Jul 11 16:59 ./jetty-6.1.14-fgw-aps.zip
8392811    8 -rw-r--r--   1 root     root         7167 Sep  9 03:26 ./cpsapplist.prop
8393836 5788 -rw-r--r--   1 root     root      5910895 Apr  3  2011 ./jetty-distribution-7.3.0.v20110203.zip
8196335 47744 -rw-r--r--   1 root     root     48835553 Jun 30 17:51 ./moni2.tar.gz
8422513 6760 -rw-r--r--   1 root     root      6908320 Jun 30 17:51 ./apache-tomcat-6.0.30.zip
8393141    4 drwxr-xr-x   2 root     root         4096 Jul  5 10:45 ./apache-tomcat-6.0.30

 2.与使用者或者群组名称有关的参数:

   -uid n :n 为数字,这个数字是使用者的帐号 ID,亦即 UID ,这个 UID 是记录在
            /etc/passwd 里面与帐号名称对应的数字。这方面我们会在第四篇介绍。
   -gid n :n 为数字,这个数字是群组名称的 ID,亦即 GID,这个 GID 记录在
            /etc/group,相关的介绍我们会第四篇说明~
   -user name :name 为使用者帐号名称喔,也就是按照文件属主来查找文件。
   -group name:name 为群组名称喔,按照文件所属的组来查找文件。

    -nouser 查找无有效属主的文件,即该文件的属主在/etc/passwd中不存在

    -nogroup 查找无有效所属组的文件,即该文件所属的组在/etc/groups中不存在。当你自行安装软件时,很可能该软件的属性当中并没有文件拥有者,这是可能的!在这个时候,就可以使用 -nouser 与 -nogroup 搜寻。

范例三:搜寻 /home 底下属于zhuying的文件
[root@www ~]# find /home -user zhuying
# 这个东西也很有用的~当我们要找出任何一个使用者在系统当中的所有文件时,
# 就可以利用这个命令将属于某个使用者的所有文件都找出来喔!

范例四:搜寻系统中不属于任何人的文件
[root@www ~]# find / -nouser
# 透过这个命令,可以轻易的就找出那些不太正常的文件。
# 如果有找到不属于系统任何人的文件时,不要太紧张,
# 那有时候是正常的~尤其是你曾经以原始码自行编译软件时。

如果你想要找出某个使用者在系统底下创建了啥咚咚,使用上述的选项与参数,就能够找出来啦! 至于那个 -nouser 或 -nogroup 的选项功能中,除了你自行由网络上面下载文件时会发生之外, 如果你将系统里面某个帐号删除了,但是该帐号已经在系统内创建很多文件时,就可能会发生无主孤魂的文件存在! 此时你就得使用这个 -nouser 来找出该类型的文件罗!

3. 与文件权限及名称有关的参数:
   -name filename:搜寻文件名称为 filename 的文件;
   -size [+-]SIZE:搜寻比 SIZE 还要大(+)或小(-)的文件。这个 SIZE 的规格有:c: 代表 byte(block块,一块代表512字节), k: 代表 1024bytes。所以,要找比 50KB,还要大的文件,就是『 -size +50k 』

【可以按照文件长度来查找文件,这里所指的文件长度既可以用块(block)来计量,也可以用字节来计量。以字节计量文件长度的表达形式为N c;以计量文件长度只用数字表示即可。】
   -type TYPE    :搜寻文件的类型为 TYPE 的,类型主要有:一般正规文件 (f),
                   装置文件 (b块设备文件, c字符设备文件), 目录 (d), 连结档 (l符号链接文件), socket (s)
                   及 FIFO (p管道文件) 等属性。
   -perm mode  :搜寻文件权限『刚好等於』 mode 的文件,这个 mode 为类似 chmod
                 的属性值,举例来说, -rwsr-xr-x 的属性为 4755 !
   -perm -mode :搜寻文件权限『必须要全部囊括 mode 的权限』的文件,举例来说,
                 我们要搜寻 -rwxr--r-- ,亦即 0744 的文件,使用 -perm -0744,
                 当一个文件的权限为 -rwsr-xr-x ,亦即 4755 时,也会被列出来,
                 因为 -rwsr-xr-x 的属性已经囊括了 -rwxr--r-- 的属性了。
   -perm +mode :搜寻文件权限『包含任一 mode 的权限』的文件,举例来说,我们搜寻
                 -rwxr-xr-x ,亦即 -perm +755 时,但一个文件属性为 -rw-------
                 也会被列出来,因为他有 -rw.... 的属性存在!


范例五:找出档名为 passwd 这个文件
[root@www ~]# find / -name passwd
# 利用这个 -name 可以搜寻档名啊!

范例六:找出 /var 目录下,文件类型为 Socket 的档名有哪些?
[root@www ~]# find /var -type s
# 这个 -type 的属性也很有帮助喔!尤其是要找出那些怪异的文件,
# 例如 socket 与 FIFO 文件,可以用 find /var -type p 或 -type s 来找!

范例七:搜寻文件当中含有 SGID 或 SUID 或 SBIT 的属性
[root@www ~]# find / -perm +7000
# 所谓的 7000 就是 ---s--s--t ,那么只要含有 s 或 t 的就列出,
# 所以当然要使用 +7000 ,使用 -7000 表示要含有 ---s--s--t 的所有三个权限,
# 因此,就是 +7000 ~了乎?

上述范例中比较有趣的就属 -perm 这个选项啦!他的重点在找出特殊权限的文件罗! 我们知道 SUID 与 SGID 都可以配置在二进位程序上,假设我想要找出来 /bin, /sbin 这两个目录下, 只要具有 SUID 或 SGID 就列出来该文件,你可以这样做:
[root@www ~]# find /bin /sbin -perm +6000
因为 SUID 是 4 分,SGID 2 分,总共为 6 分,因此可用 +6000 来处理这个权限! 至於 find 后面可以接多个目录来进行搜寻!另外, find 本来就会搜寻次目录,这个特色也要特别注意喔! 最后,我们再来看一下 find 还有什么特殊功能吧!

4.其他一些不常用的参数:

 -newer file:file为一个存在的文件,列出比file还要

-newer file1 ! file2查找更改时间比文件file1新但比文件file2旧的文件。

-prune :使用这一选项可以使find命令不在当前指定的目录中查找,如果同时使用-depth选项,那么-prune将被find命令忽略。
-depth在查找文件时,首先查找当前目录中的文件,然后再在其子目录中查找。
-fstype:查找位于某一类型文件系统中的文件,这些文件系统类型通常可以在配置文件/etc/fstab中找到,该配置文件中包含了本系统中有关文件系统的信息。
-mount:在查找文件时不跨越文件系统mount点。
-follow:如果find命令遇到符号链接文件,就跟踪至链接所指向的文件
-cpio:对匹配的文件使用cpio命令,将这些文件备份到磁带设备中。

5 额外可进行的动作:
   -exec command :command 为其他命令,-exec 后面可再接额外的命令来处理搜寻到 的结果。
   -print:将结果列印到萤幕上,这个动作是默认动作!

范例八:将上个范例找到的文件使用 ls -l 列出来~
[root@www ~]# find / -perm +7000 -exec ls -l {} \;
# 注意到,那个 -exec 后面的 ls -l 就是额外的命令,命令不支持命令别名
# 所以仅能使用 ls -l 不可以使用 ll!注意注意!

范例九:找出系统中,大于 1MB 的文件
[root@www ~]# find / -size +1000k
# 虽然在 man page 提到可以使用 M 与 G 分别代表 MB 与 GB,
# 不过,俺却试不出来这个功能~所以,目前应该是仅支持到 c 与 k 吧

find 的特殊功能就是能够进行额外的动作(action)。我们将范例八的例子以图解来说明如下:

***Linux文件查找命令find***

  • {} 代表的是『由 find 找到的内容』,如上图所示,find 的结果会被放置到 {} 位置中;
  • -exec 一直到 \; 是关键字,代表 find 额外动作的开始 (-exec) 到结束 (\;) ,在这中间的就是 find 命令内的额外动作。 在本例中就是『 ls -l {} 』罗!
  • 因为 ;在 bash 环境下是有特殊意义的,因此利用反斜线来跳脱

记住:在shell中用任何方式删除文件之前,应当先查看相应的文件,一定要小心!当使用诸如mv或rm命令时,可以使用-exec选项的安全模式。它将在对每个匹配到的文件进行操作之前提示你。

在下面的例子中, find命令在当前目录中查找所有文件名以.conf结尾、更改时间在5日以上的文件,并删除它们,只不过在删除之前先给出提示。

 [root@www~]#
[root@www ~]# find . -name "*.conf"  -mtime +5 -ok rm {}  \;
< rm ... ./zy.bak/memcached-1.4.5/t/sasl/memcached.conf > ?

 按y键删除文件,按n键不删除。

任何形式的命令都可以在-exec选项中使用。

在下面的例子中我们使用grep命令。find命令首先匹配所有文件名为“ passwd*”的文件,例如passwd、passwd.old、passwd.bak,然后执行grep命令看看在这些文件中是否存在一个sam用户。

[root@www ~]# find /etc -name "passwd*" -exec grep zhuying {} \;

zhuying:x:502:503::/home/zhuying:/bin/bash

四。find命令的例子;

1、查找当前用户主目录下的所有文件:
下面两种方法都可以使用
$ find $HOME -print
$ find ~  -print(或者find ~ -name "*" -print

2、显示当前目录中文件属主具有读、写权限,并且文件所属组的用户和其他用户具有读权限的文件;
$ find . -type f -perm 644 -exec ls -l {} \;

3、为了查找系统中所有文件长度为0的普通文件,并列出它们的完整路径;
$ find / -type f -size 0 -exec ls -l {} \;

4、查找/var/logs目录中更改时间在7日以前的普通文件,并在删除之前询问它们;
$ find /var/logs -type f -mtime +7 -ok rm {} \;

5、为了查找系统中所有属于root组的文件;
$find . -group root -exec ls -l {} \;
-rw-r--r--    1 root     root          595 10月 31 01:09 ./fie1

6、find命令将删除当目录中访问时间在7日以来、含有数字后缀的admin.log文件。
该命令只检查三位数字,所以相应文件的后缀不要超过999。先建几个admin.log*的文件 ,才能使用下面这个命令
$ find . -name "admin.log[0-9][0-9][0-9]" -atime -7  -ok
rm {} \;
< rm ... ./admin.log001 > ? n
< rm ... ./admin.log002 > ? n
< rm ... ./admin.log042 > ? n
< rm ... ./admin.log942 > ? n

7、使用type选项
$ find . -type d |sort【为了查找当前文件系统中的所有目录并排序】

$ find /etc -type d -print【在/etc目录下查找所有的目录】

$ find . ! -type d -print【在当前目录下查找除目录以外的所有类型的文件】

$ find /etc -typel -print【在/etc目录下查找所有的符号链接文件】

8、为了查找系统中所有的rmt磁带设备;
$ find /dev/rmt -print

9.使用name选项

文件名选项是find命令最常用的选项,要么单独使用该选项,要么和其他选项一起使用。

可以使用某种文件名模式来匹配文件,记住要用引号将文件名模式引起来。

$ find ~ -name "*.txt" -print

$ find . -name "*.txt" -print(在当前目录及子目录中查找所有的‘ *.txt’文件)

$ find . -name "[A-Z]*" -print(在当前目录及子目录中查找文件名以一个大写字母开头的文件)

$ find /etc -name "host*" -print(在/etc目录中查找文件名以host开头的文件)

$ find / -name "*" -print(让系统高负荷运行,就从根目录开始查找所有的文件)

$find . -name "[a-z][a-z][0--9][0--9].txt"
-print【在当前目录查找文件名以两个小写字母开头,跟着是两个数字,最后是.txt的文件】

10.用perm选项

按照文件权限模式用-perm选项,按文件权限模式来查找文件的话。最好使用八进制的权限表示法。

$ find . -perm 755 -print(文件属主可以读、写、执行,其他用户可以读、执行的文件)

还有一种表达方法:在八进制数字前面要加一个横杠-,表示都匹配,如-007就相当于777,-006相当于666

测试下来发现有问题,正确的理解-007应该是至少007的意思

find . -perm -220

find . -perm -g+w,u+w【以上两种写法是相同的,就是属主和属组都有写权限】

find . -perm -444 -perm /222 ! -perm /111

find . -perm -a+r -perm /a+w ! -perm /a+x【以上这两种方法是相同的,就是所有用户至少有可读权限,但没有可执行权限】

小节:

-perm mode:文件许可正好符合mode

-perm +mode:文件许可部分符合mode

-perm -mode: 文件许可至少符合mode

11。忽略某个目录

如果在查找文件时希望忽略某个目录,因为你知道那个目录中没有你所要查找的文件,那么可以使用-prune选项来指出需要忽略的目录。在使用-prune选项时要当心,因为如果你同时使用了-depth选项,那么-prune选项就会被find命令忽略

$ find /apps -path "/apps/bin" -prune -o -print【希望在/apps目录下查找文件,但不希望在/apps/bin目录下查找】

12。使用find查找文件的时候怎么避开某个文件目录
find [-path ..] [expression] 在路径列表的后面的是表达式

-path "/usr/sam" -prune -o -print 是 -path "/usr/sam" -a -prune -o

-print 的简写表达式按顺序求值, -a 和 -o 都是短路求值,与 shell 的 && 和 || 类似如果 -path "/usr/sam" 为真,则求值 -prune , -prune 返回真,与逻辑表达式为真;否则不求值 -prune,与逻辑表达式为假。如果 -path "/usr/sam" -a -prune 为假,则求值 -print ,-print返回真,或逻辑表达式为真;否则不求值 -print,或逻辑表达式为真。

这个表达式组合特例可以用伪码写为

if -path "/usr/sam"  then
          -prune
else
          -print

避开多个文件夹

# find /root/zy \( -path /root/zy/memcached-1.4.5 -o -path /root/zy/backup \) -prune -o -print

圆括号表示表达式的结合。

\ 表示引用,即指示 shell 不对后面的字符作特殊解释,而留给 find 命令去解释其意义。

查找某一确定文件,-name等选项加在-o 之后

# find /root/zy.bak/ \( -path /root/zy.bak/memcached-1.4.5 -o -path /root/zy.bak/jdk1.6.0_05/ \) -prune -o -name "demo" -print【注意:这里可是只显示文件的路径,不显示其子目录

/root/zy.bak/jdk1.6.0_05/demo
/root/zy.bak/jdk1.6.0_05/demo/scripting/jconsole-plugin/src/com/sun/demo
/root/zy.bak/jdk1.6.0_05/db/demo

13.使用size选项

可以按照文件长度来查找文件,这里所指的文件长度既可以用块(block)来计量,也可以用字节来计量。以字节计量文件长度的表达形式为N c;以块计量文件长度只用数字表示即可。

在按照文件长度查找文件时,一般使用这种以字节表示的文件长度,在查看文件系统的大小,因为这时使用块来计量更容易转换。

$ find . -size +1000000c -print【在当前目录下查找文件长度大于1 M字节的文件】 也可以用find . -size +1M -print表示 $ find /home/apache -size 100c -print【在/home/apache目录下查找文件长度恰好为100字节的文件】

$ find . -size +10 -print【在当前目录下查找长度超过10块的文件(一块等于512字节)】
 14。使用depth选项

在使用find命令时,可能希望先匹配所有的文件,再在子目录中查找。使用depth选项就可以使find命令这样做。这样做的一个原因就是,当在使用find命令向磁带上备份文件系统时,希望首先备份所有的文件,其次再备份子目录中的文件。

在下面的例子中, find命令从文件系统的根目录开始,查找一个名为CON.FILE的文件。

它将首先匹配所有的文件然后再进入子目录中查找。

$ find / -name "CON.FILE" -depth -print【测试下来发现出问题,然后查了文档,说这个有bug我换成以下的方式就没有再报错】

$ find / -depth -name "CON.FILE" -print【正确格式】

15。使用mount选项

在当前的文件系统中查找文件(不进入其他文件系统),可以使用find命令的mount选项。

从当前目录开始查找位于本文件系统中文件名以zip结尾的文件:

$ find . -name "*.zip" -mount -print【测试下来发现出问题,然后查了文档,说这个有bug我换成以下的方式就没有再报错】

find . -mount -name "*.zip" -print【正确格式】

16.xargs处理

find命令配合使用exec和xargs可以使用户对所匹配到的文件执行几乎所有的命令。

(1.)用grep命令在当前目录下的所有普通文件中搜索hostnames这个词:
find . -name \* -type f -print | xargs grep -i "hostname"
find . -type f -print | xargs grep -i "hostname"

find . -name "*"-type f -print | xargs grep -i "hostname"【三者相同】
注意:在上面的例子中, \用来取消find命令中的*在shell中的特殊含义。

(2.)查看所有以jdk开头文件的文件类型

# find . -name "jdk*" -type f -print | xargs file
./jdk1.6.0_25.tar.gz:    gzip compressed data, from Unix, last modified: Wed Jun 29 14:03:13 2011
./jdk.sh:                Bourne-Again shell script text executable
./jdk-6u5-linux-x64.bin: Bourne shell script text executable

(3.)在整个系统中查找内存信息转储文件(core dump),然后把结果保存到/tmp/core.log 文件
#find / -name "core" -print|xargs echo "" > /tmp/core.log

(4.)在当前目录下查找所有用户具有读、写和执行权限的文件,并收回相应的写权限:
#find . -perm 777 -print | xargs chmod o-w

(5.)查找查找2011-11-11 03:41:54时更改过的jdk文件
#find ./ -name "jdk*"
./jdk1.6.0_25.tar.gz
./jdk.sh
./jdk-6u5-linux-x64.bin
#find ./ -name "jdk*"|xargs ls -l --full-time2>/dev/null
-rwxr-xr-x 1 root root  63724381 2011-11-11 03:41:55.000000000 +0800 ./jdk-6u5-linux-x64.bin
-rw-r--r-- 1 root root       421 2011-10-28 17:15:31.000000000 +0800 ./jdk.sh
-rw-r--r-- 1 root root 102897638 2011-11-11 03:41:54.000000000 +0800 ./jdk1.6.0_25.tar.gz
# find ./ -name "jdk*"|xargs ls -l --full-time2>/dev/null|grep "2011-11-11 03:41:54"
-rw-r--r-- 1 root root 102897638 2011-11-11 03:41:54.000000000 +0800 ./jdk1.6.0_25.tar.gz

最后再加上一个我们可能会经常用到的,就是查找某些规定大小的文件,然后移动到某个目录去,之前一直尝试找不到问题,后来替换了一下顺序就ok了,(*^__^*) 嘻嘻……

find . -size +90M -print -exec mv {} /root/zy/soft/ \;【一定要注意顺序哦,就像我们移动文件时一样,是需要顺序的~】