Linux【2】-管理文件-1-6-查找文本--find

[root@www ~]# find [PATH] [option] [action]

常用的几个命令:

find /tmp -size -3k -ls
在tmp下文件大小小于3k的文件呈现出来

find /tmp -size +10c -ls
找到比10个字节大的文件

find /tmp -user root -ls
tmp下用户名为root的文件

find /tmp -perm 754 -ls
文件权限为754的文件
    
find /tmp \(-size +1k -a -10M -amin -30 -a type f \) -ls
-a用来连接条件,多个条件用-a (与)连接起来 (还有两个连接词: -o 或;! 非)    

find / -perm +7000 -exec ls -l {} \;
{}表示找到的恩建,-exec 后接bash命令  最后还有\;表示命令的结束。
-OK可以代替-exec  给出提示,让用户来选择是否执行

一、参数

1.与时间有关的选项:共有 -atime, -ctime 与 -mtime ,以 -mtime 说明

-mtime  n :n 为数字,意义为在 n 天之前的『一天之内』被更动过内容的文件;
-mtime +n :列出在 n 天之前(不含 n 天本身)被更动过内容的文件档名;
-mtime -n :列出在 n 天之内(含 n 天本身)被更动过内容的文件档名。
-newer file :file 为一个存在的文件,列出比 file 还要新的文件档名
 
-atime 文件被读取/执行时间
-ctime 文件属性修改时间
-mtime  文件修改时间

+,会把不足一个时间单位的时间取下整,再与条件值比较。 例如, 一个文件mtime为1day12hour ago,则符合 -mtime 1,但不符合 -mtime +1。 1day12hour ,即1.5天,取上整为1day,因此不符合-mtime +1。   下面的这条语句,前者保留最近2天的日志,后者则是一天之内的。   find /path -type f -name “.log” -mtime +1 -exec rm {} /; find /path -type f -name “.log” -mtime 1 -exec rm {} /;

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

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

范例二:寻找 /etc 底下的文件,如果文件日期比 /etc/passwd 新就列出

[root@www ~]# find /etc -newer /etc/passwd
# -newer 用在分辨两个文件之间的新旧关系是很有用的!

时间参数真是挺有意思的!我们现在知道 atime, ctime 与 mtime 的意义,如果你想要找出一天内被更动过的文件名, 可以使用上述范例一的作法。但如果我想要找出『4天内被更动过的文件档名』呢?那可以使用『 find /var -mtime -4 』。那如果是『4天前的那一天』就用『 find /var -mtime 4 』。有没有加上『+, -』差别很大喔!我们可以用简单的图示来说明一下:

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

参数:
-uid n :n 为数字,这个数字是用户的账号 ID,亦即 UID ,这个 UID 是记录在
        /etc/passwd 里面与账号名称对应的数字。这方面我们会在第四篇介绍。
-gid n :n 为数字,这个数字是组名的 ID,亦即 GID,这个 GID 记录在
        /etc/group,相关的介绍我们会第四篇说明~
-user name :name 为使用者账号名称喔!例如 dmtsai
-group name:name 为组名喔,例如 users ;
-nouser    :寻找文件的拥有者不存在/etc/passwd 的人!
-nogroup   :寻找文件的拥有群组不存在于 /etc/group 的文件!
            当你自行安装软件时,很可能该软件的属性当中并没有文件拥有者,
            这是可能的!在这个时候,就可以使用-nouser 与 -nogroup 搜寻。

范例三:搜寻 /home 底下属于 vbird 的文件

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

范例四:搜寻系统中不属于任何人的文件

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

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

3.与文件权限及名称有关的参数:

-name filename:搜寻文件名为 filename 的文件;
-size [+-]SIZE:搜寻比 SIZE 还要大(+)或小(-)的文件。这个 SIZE 的规格有:
               c: 代表 byte, k: 代表 1024bytes。所以,要找比 50KB
               还要大的文件,就是『-size +50k 』
-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.路径限制 maxdepth mindepth

清理掉1周天前的缓存目录。(该缓存使用了3层目录散列结构,缓存目录下的第三层目录才是要清理的目录)

find /path -maxdepth 3 -mindepth 3 -type d -mtime 7 -exec rm -rf {} /;

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)。我们将范例八的例子以图解来说明如下:

{} 代表的是『由 find 找到的内容』,如上图所示,find 的结果会被放置到 {} 位置中; -exec 一直到 ; 是关键词,代表 find 额外动作的开始(-exec) 到结束 (;) ,在这中间的就是 find 指令内的额外动作。 在本例中就是『 ls -l {} 』啰! 因为『 ; 』在 bash 环境下是有特殊意义的,因此利用反斜杠来跳脱。 透过图 5.2.2 你应该就比较容易了解 -exec 到 ; 之间的意义了吧!

如果你要找的文件是具有特殊属性的,例如 SUID 、文件拥有者、文件大小等等, 那么利用 locate 是没有办法达成你的搜寻的!此时 find 就显的很重要啦! 另外,find 还可以利用通配符来找寻档名呢!举例来说,你想要找出 /etc 底下檔名包含 httpd 的文件, 那么你就可以这样做:

[root@www ~]# find /etc -name '*httpd*'

不但可以指定搜寻的目录(连同次目录),并且可以利用额外的选项与参数来找到最正确的档名!真是好好用! 不过由于 find 在寻找数据的时后相当的操硬盘!所以没事情不要使用 find 啦!有更棒的指令可以取代呦!那就是上面提到的 whereis 与 locate 啰!

二、具体案例

首先建立如下文件和文件夹,用于后续的搜索

# vim create_sample_files.sh
touch MybashProgram.sh
touch mycprogram.c
touch MyCProgram.c
touch Program.c

mkdir backup
cd backup

touch MybashProgram.sh
touch mycprogram.c
touch MyCProgram.c
touch Program.c

# chmod +x create_sample_files.sh

# ./create_sample_files.sh

# ls -R
.:
backup                  MybashProgram.sh  MyCProgram.c
create_sample_files.sh  mycprogram.c      Program.c

./backup:
MybashProgram.sh  mycprogram.c  MyCProgram.c  Program.c

2.1 通过名字查找文件

# find -name "MyCProgram.c"
./backup/MyCProgram.c
./MyCProgram.c

2.2 忽略名字的大小写

# find -iname "MyCProgram.c"
./mycprogram.c
./backup/mycprogram.c
./backup/MyCProgram.c
./MyCProgram.c

2.3 限定搜索的目录深度

# find / -name passwd
./usr/share/doc/nss_ldap-253/pam.d/passwd
./usr/bin/passwd
./etc/pam.d/passwd
./etc/passwd

在根目录下一级找到passwd文件。 (即根目录1级和一个子目录2级)

# find -maxdepth 2 -name passwd
./etc/passwd

在根目录下两个级别下找到passwd文件。

# find / -maxdepth 3 -name passwd
./usr/bin/passwd
./etc/pam.d/passwd
./etc/passwd

在子目录级别2和4之间找到密码文件。

# find -mindepth 3 -maxdepth 5 -name passwd
./usr/bin/passwd
./etc/pam.d/passwd

2.4 在“查找”命令找到的文件上执行命令

在下面的示例中,find命令计算名称为MyCProgram.c的所有文件的md5sum(忽略大小写)。 {}替换为当前文件名。

# find -iname "MyCProgram.c" -exec md5sum {} \;

d41d8cd98f00b204e9800998ecf8427e  ./mycprogram.c
d41d8cd98f00b204e9800998ecf8427e  ./backup/mycprogram.c
d41d8cd98f00b204e9800998ecf8427e  ./backup/MyCProgram.c
d41d8cd98f00b204e9800998ecf8427e  ./MyCProgram.c

2.5 反转匹配

显示名称不是MyCProgram.c的文件或目录。由于maxdepth为1,因此只能在当前目录下查看。

# find -maxdepth 1 -not -iname "MyCProgram.c"
.
./MybashProgram.sh
./create_sample_files.sh
./backup
./Program.c

2.6 通过其索引节点号查找文件

每个文件都有一个唯一的索引节点号,使用它我们可以识别该文件。 创建两个名称相似的文件。 即一个文件,文件末尾有空格。

# touch "test-file-name"

# touch "test-file-name "
[Note: There is a space at the end]

# ls -1 test*
test-file-name
test-file-name

从ls输出中,您无法确定哪个文件的末尾有空格。 使用选项-i,您可以查看文件的inode编号,这对于这两个文件而言是不同的。

# ls -i1 test*
16187429 test-file-name
16187430 test-file-name

您可以在find命令上指定inode编号,如下所示。 在此示例中,find命令使用索引节点号重命名文件。

# find -inum 16187430 -exec mv {} new-test-file-name \;

# ls -i1 *test*
16187430 new-test-file-name
16187429 test-file-name

当您要对名称不正确的文件进行某些操作时,可以使用此技术,如以下示例所示。 例如,名称为file?.txt的文件中包含特殊字符。 如果尝试执行“ rm file?.txt”,则以下三个文件将全部删除。 因此,请按照以下步骤仅删除“ file?.txt”文件。

# ls
file1.txt  file2.txt  file?.txt

查找每个文件的索引节点号

# ls -i1
804178 file1.txt
804179 file2.txt
804180 file?.txt

使用索引节点号删除其中包含特殊字符的文件,如下所示

# find -inum 804180 -exec rm {} \;

# ls
file1.txt  file2.txt
[Note: The file with name "file?.txt" is now removed]

2.7 根据文件权限查找文件

可以进行以下操作。

  • 查找与完全许可匹配的文件
  • 检查给定的权限是否匹配,与其他权限位无关
  • 通过给出八进制/符号表示进行搜索

对于此示例,让我们假设目录包含以下文件。 请注意,这些文件的文件权限不同。

# ls -l
total 0
-rwxrwxrwx 1 root root 0 2009-02-19 20:31 all_for_all
-rw-r--r-- 1 root root 0 2009-02-19 20:30 everybody_read
---------- 1 root root 0 2009-02-19 20:31 no_for_all
-rw------- 1 root root 0 2009-02-19 20:29 ordinary_file
-rw-r----- 1 root root 0 2009-02-19 20:27 others_can_also_read
----r----- 1 root root 0 2009-02-19 20:27 others_can_only_read

查找具有读取权限的文件进行分组。 使用以下命令在您的主目录中查找世界可以读取的所有文件,而与该文件的其他权限无关。

# find . -perm -g=r -type f -exec ls -l {} \;
-rw-r--r-- 1 root root 0 2009-02-19 20:30 ./everybody_read
-rwxrwxrwx 1 root root 0 2009-02-19 20:31 ./all_for_all
----r----- 1 root root 0 2009-02-19 20:27 ./others_can_only_read
-rw-r----- 1 root root 0 2009-02-19 20:27 ./others_can_also_read

查找仅具有读取权限才能分组的文件。

# find . -perm g=r -type f -exec ls -l {} \;
----r----- 1 root root 0 2009-02-19 20:27 ./others_can_only_read

查找仅具有读取权限的文件才能分组[按八进制搜索]

# find . -perm 040 -type f -exec ls -l {} \;
----r----- 1 root root 0 2009-02-19 20:27 ./others_can_only_read

2.8 在您的主目录及其子目录中找到所有空文件(零字节文件)

以下命令输出的大多数文件将是其他应用程序创建的锁定文件和占位符

# find ~ -empty

仅列出主目录中的所有空文件。

# find . -maxdepth 1 -empty

仅列出当前目录中的非隐藏空文件。

# find . -maxdepth 1 -empty -not -name ".*"

2.9 查找前5个大文件

以下命令将显示当前目录及其子目录中的前5大文件。 根据命令必须处理的文件总数,这可能需要一段时间才能执行。

# find . -type f -exec ls -s {} \; | sort -n -r | head -5

2.10 查找前5个小文件

技术与查找更大的文件相同,但是排序的唯一区别是升序。

# find . -type f -exec ls -s {} \; | sort -n  | head -5

查找小于4k的文件,并删除

find ./ -size -2k |xargs rm -fr

在上面的命令中,您很可能只会看到零字节文件(空文件)。 因此,您可以使用以下命令列出除ZERO字节文件以外的较小文件。

# find . -not -empty -type f -exec ls -s {} \; | sort -n  | head -5

2.11 使用选项-type根据文件类型查找文件

仅查找socket文件。

# find . -type s

查找所有目录

# find . -type d

仅查找普通文件

# find . -type f

查找所有隐藏的文件

# find . -type f -name ".*"

查找所有隐藏的目录

# find -type d -name ".*"

2.12 通过与其他文件的修改时间进行比较来查找文件

显示在指定文件之后被修改的文件。 以下find命令显示在normal_file之后创建/修改的所有文件。

# ls -lrt
total 0
-rw-r----- 1 root root 0 2009-02-19 20:27 others_can_also_read
----r----- 1 root root 0 2009-02-19 20:27 others_can_only_read
-rw------- 1 root root 0 2009-02-19 20:29 ordinary_file
-rw-r--r-- 1 root root 0 2009-02-19 20:30 everybody_read
-rwxrwxrwx 1 root root 0 2009-02-19 20:31 all_for_all
---------- 1 root root 0 2009-02-19 20:31 no_for_all

# find -newer ordinary_file
.
./everybody_read
./all_for_all
./no_for_all

2.13 按大小查找文件

使用-size选项,可以按大小查找文件。

查找大于给定大小的文件

# find ~ -size +100M

查找小于给定大小的文件

# find ~ -size -100M

查找与给定大小完全匹配的文件

# find ~ -size 100M

注意:–表示小于给定大小,+表示大于给定大小,没有符号表示精确给定大小。

2.14 为常用查找操作创建别名

如果您发现某些东西非常有用,则可以将其作为别名。 并随时执行它。

经常删除名称为a.out的文件。

# alias rmao="find . -iname a.out -exec rm {} \;"
# rmao

删除c程序生成的核心文件。

# alias rmc="find . -iname core -exec rm {} \;"
# rmc

2.15 使用find命令删除大型存档文件

以下命令将删除超过100M的* .zip文件。

# find / -type f -name *.zip -size +100M -exec rm -i {} \;"

使用别名rm100m删除所有超过100M的* .tar文件(删除100M)。 使用类似的概念并创建rm1g,rm2g,rm5g之类的别名,以分别删除大于1G,2G和5G的文件大小。

# alias rm100m="find / -type f -name *.tar -size +100M -exec rm -i {} \;"
# alias rm1g="find / -type f -name *.tar -size +1G -exec rm -i {} \;"
# alias rm2g="find / -type f -name *.tar -size +2G -exec rm -i {} \;"
# alias rm5g="find / -type f -name *.tar -size +5G -exec rm -i {} \;"

# rm100m
# rm1g
# rm2g
# rm5g

三、我的案例

3.1 找到相关的文件,并进行合并

find ./ -name 'final_seq.fa' -exec cat  {} + > result/nsp_final.fa

参考资料

药企,独角兽,苏州。团队长期招人,感兴趣的都可以发邮件聊聊:tiehan@sina.cn
个人公众号,比较懒,很少更新,可以在上面提问题,如果回复不及时,可发邮件给我: tiehan@sina.cn