linux之find命令详解

查找文件
find ./ -type f

查找目录
find ./ -type d

查找名字为test的文件或目录
find ./ -name test

查找名字符合正则表达式的文件,注意前面的‘.*’(查找到的文件带有目录)
find ./ -regex .*so.*\.gz

查找目录并列出目录下的文件(为找到的每一个目录单独执行ls命令,没有选项-print时文件列表前一行不会显示目录名称)
find ./ -type d -print -exec ls {} \;

查找目录并列出目录下的文件(为找到的每一个目录单独执行ls命令,执行命令前需要确认)
find ./ -type d -ok ls {} \;

查找目录并列出目录下的文件(将找到的目录添加到ls命令后一次执行,参数过长时会分多次执行)
find ./ -type d -exec ls {} +

查找文件名匹配*.c的文件
find ./ -name \*.c

打印test文件名后,打印test文件的内容
find ./ -name test -print -exec cat {} \;

不打印test文件名,只打印test文件的内容
find ./ -name test -exec cat {} \;

查找文件更新日时在距现在时刻二天以内的文件
find ./ -mtime -2

查找文件更新日时在距现在时刻二天以上的文件
find ./ -mtime +2

查找文件更新日时在距现在时刻一天以上二天以内的文件
find ./ -mtime 2

查找文件更新日时在距现在时刻二分以内的文件
find ./ -mmin -2

查找文件更新日时在距现在时刻二分以上的文件
find ./ -mmin +2

查找文件更新日时在距现在时刻一分以上二分以内的文件
find ./ -mmin 2

查找文件更新时间比文件abc的内容更新时间新的文件
find ./ -newer abc

查找文件访问时间比文件abc的内容更新时间新的文件
find ./ -anewer abc

查找空文件或空目录
find ./ -empty

查找空文件并删除
find ./ -empty -type f -print -delete

查找权限为644的文件或目录(需完全符合)
find ./ -perm 664

查找用户/组权限为读写,其他用户权限为读(其他权限不限)的文件或目录
find ./ -perm -664

查找用户有写权限或者组用户有写权限的文件或目录
find ./ -perm /220
find ./ -perm /u+w,g+w
find ./ -perm /u=w,g=w

查找所有者权限有读权限的目录或文件
find ./ -perm -u=r

查找用户组权限有读权限的目录或文件
find ./ -perm -g=r

查找其它用户权限有读权限的目录或文件
find ./ -perm -o=r

查找所有者为lzj的文件或目录
find ./ -user lzj

查找组名为gname的文件或目录
find ./ -group gname

查找文件的用户ID不存在的文件
find ./ -nouser

查找文件的组ID不存在的文件
find ./ -nogroup

查找有执行权限但没有可读权限的文件
find ./ -executable \! -readable

查找文件size小于10个字节的文件或目录
find ./ -size -10c

查找文件size等于10个字节的文件或目录
find ./ -size 10c

查找文件size大于10个字节的文件或目录
find ./ -size +10c

查找文件size小于10k的文件或目录
find ./ -size -10k

查找文件size小于10M的文件或目录
find ./ -size -10M

查找文件size小于10G的文件或目录
find ./ -size -10G


 

首先需要在你的主目录下创建以下示例文件,这些文件会在后面的示例中使用:

# 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

使用名称查找

这是 find 命令最基本的用法。下面命令会在当前目录和所有子目录拉中查找所有名叫 'MyCProgram.c' 的文件:

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

2. 按照名称查找文件,忽略大小写

同上例,不过这次会忽略大小写,你懂的。

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

3. 使用 'mindepth' 和 'maxdepth' 限制查找的路径深度

从根目录开始查找所有 'passwd' 文件:

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

从根目录开始查找所有 'passwd' 文件,仅往下查找一层子目录(比如:/ -- level 1,任意子目录 -- level 2):

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

从根目录开始查找所有 'passwd' 文件,仅往下查找两层子目录(比如:/ -- level 1,任意子目录 -- level 2):

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

在第2层和第4层子目录中查找 'passwd' 文件:

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

4. 根据查找到的文件执行命令

下面例子中,find 命令会为每个查找到的文件计算 md5 值, {} 会被当前找到的文件替换:

# find -iname "MyCProgram.c" -exec md5sum {} \;
d41d8cd98f00b204e9800998ecf8427e  ./mycprogram.c
d41d8cd98f00b204e9800998ecf8427e  ./backup/mycprogram.c
d41d8cd98f00b204e9800998ecf8427e  ./backup/MyCProgram.c
d41d8cd98f00b204e9800998ecf8427e  ./MyCProgram.c

5. 反向查找

下面例子查找所有名称不是 'MyCProgram.c' 的文件,只查找当前层子目录(maxdepth 为1):

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

6. 根据 inode 号查找文件

Linux 操作系统中,每一个文件都有唯一的 inode 序号,可以用来唯一标识这个文件。这个例子中我们将创建两个相似的文件,比如:在一个文件文件名后加一个空格:

# 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

嗯,从下面的输出中,你能分辨出那个是你要找的文件吗?通过 '-i' 选项,你可以查看找到文件的 inode 号,这个肯定是不一样的:

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

这样,你可以通过 inode 号来查找文件,并将文件名修改成一个容易区分的名字:

# 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 那么例子中的所有三个文件都会被删除(?是通配符,匹配0-1个字符,懂了吧),可以通过以下步骤删除该死的 'file?.txt':

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

找到每个文件的 inode 号:

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

根据 inode 号来删除 'file?.txt':

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

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

7. 根据文件权限来查找文件

下面的操作可以: 1. 根据明确指定的权限来查找文件 2. 仅检查给定的权限是否匹配,忽略其他的权限位 3. 根据给定的八进制或者符号描述的权限进行搜索

下面例子中,我们假设文件中包含以下文件,注意,每个文件的权限是不同的

# 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

找到仅允许同组人可读的文件(按照8进制定义查找):

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

8. 在主目录及子目录中查找空文件(0字节文件)

这类文件大部分是其他应用程序创建的锁文件和占位符文件

# find ~ -empty

列出主目录下所有空文件

# find . -maxdepth 1 -empty

列出当前目录下所有非隐藏的空文件

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

9. 查找最大的5个文件

下面例子会在当前目录以及子目录中查找最大的5个文件,根据目录树的大小,所花费的时间是不同的:

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

10. 查找最小的5个文件

同上,不过这次是查找最小的5个

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

上面例子可能会看到所有的最小文件都是空文件,因此使用下面的方式过滤掉空文件:

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

11. 根据文件类型查找文件

仅查找 socket 文件

# find . -type s

查找所有目录

# find . -type d

仅查找普通文件

# find . -type f

查找所有隐藏文件

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

查找所有隐藏目录

# find -type d -name ".*"

12. 根据其他文件的修改时间对比查找文件

找到比指定文件修改时间晚的文件,下面例子列出所有在 'ordinary_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

13. 根据文件大小查找文件

使用 '-size' 选项可以根据文件大小查找文件。

查找大于某个大小的所有文件:

# find ~ -size +100M

查找小于某个大小的所有文件

# find ~ -size -100M

查找等于某个大小的所有文件

# find ~ -size 100M

注:'-' 代表小于,'+' 代表大于,没有符号代表等于。

常用的 find 命令别名

如果你觉得一些命令特别有用,你可以将这个命令创建成别名,然后你就可以在任何地方使用它了。

经常要删除 'a.out' ?

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

经常要删除 c 程序的 core 文件?

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

15. 使用 find 命令删除大归档文件

下面例子将删除大小超过 100M 的 '.zip' 文件

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

创建删除所有超过 100M 的 '.tar' 文件的命令别名,当然可以使用同样的方式创建删除 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

find 命令第二部分

一、根据访问、编辑、修改时间查找文件

可以根据文件的下面三种时间属性来查找文件:

  1. 访问时间(access time):文件被访问时该时间会更新

  2. 编辑时间(modifictaion time):文件被编辑时该时间会更新

  3. 修改时间(change time):文件 inode 数据变化时会修改改时间。

在下面的例子中将用到的选项 min 和选项 time 的说明:

  1. min:代表分钟(minute),比如:min 60 = 60 分钟(1小时)

  2. time:代表24小时制,比如:time 2 = 2*24小时(2天)

  3. 当进行24小时计算时,小数部分会被忽略,因此25小时会按照24小时处理,47小时也会按照24小时处理。只有48小时会按照48小时处理。更多可以参考 find 命令帮助中 -atime 章节。

示例1:查找1小时内修编辑的文件

要根据编辑时间查找可以使用 选项 -mmin 和 -mtime,下面是手册中对这两个选项的定义:

  1. -mmin n:文件数据在 n 分钟前被编辑

  2. -mtime n:文件数据在 n*24 小时前被编辑

下面例子在当前目录及子目录中查找1小时内被编辑过的文件

# find . -mmin -60

下面的例子从根目录开始查找1天内被编辑过的文件

# find / -mtime -1

示例2:查找1小时前被访问过的文件

要根据文件访问时间进行查找,可以使用 -amin 和 -atime 选项,下面是文档中关于这两个选项的说明:

  1. -amin n:n 分钟前被访问过

  2. -atime n:n*24 小时前被访问过

下面例子在当前目录和子目录查找1小时内被访问过的文件

# find -amin -60

同样,在根目录查找24小时内被访问过的文件

# find / -atime -1

实例3. 查找1小时前被修改的文件

要根据文件 inode 修改时间来查找文件,可以使用 -cmin 和 -ctime 选项,下面是这两个选项文档中的说明:

  1. -cmin n:文件状态 n 分钟前被修改过

  2. -ctime n:文件状态 n*24 小时前被修改过

下面例子在当前面目录和子目录查找1小时内被修改过的文件:

# find . -cmin -60

同样,在根目录查找24小时内被修改过的文件

# find / -ctime -1

示例4. 仅查找文件

上面例子中的输出结果会显示目录,因为访问文件必须先访问目录。不过,如果仅希望列出被修改过的文件,可以使用 -type f 选项,参考下面例子:

# find /etc/sysconfig -amin -30
.
./console
./network-scripts
./i18n
./rhn
./rhn/clientCaps.d
./networking
./networking/profiles
./networking/profiles/default
./networking/profiles/default/resolv.conf
./networking/profiles/default/hosts
./networking/devices
./apm-scripts
[Note: The above output contains both files and directories]

# find /etc/sysconfig -amin -30 -type f
./i18n
./networking/profiles/default/resolv.conf
./networking/profiles/default/hosts
[Note: The above output contains only files]

示例5. 仅查找非隐藏文件

如果不希望查找结果显示隐藏文件,可以使用下面的正则表达式,下面例子显示过去15分钟内被编辑过的文件,并仅显示非隐藏文件:

# find . -mmin -15 \( ! -regex ".*/\..*" \)

二、相对查找

当我们要找到在 'test' 文件编辑后我做编辑过的文件,我们可以使用这里列出的方法查找相对于某个文件编辑时间的其他文件。

示例6. 查找编辑时间相对于某个文件比较新的文件

语法:

Syntax: find -newer FILE

下面例子列出编辑时间比 '/etc/passwd' 新的文件:

# find -newer /etc/passwd

示例7. 查找编辑时间相对于某个文件比较旧的文件

语法:

Syntax: find -anewer FILE

下面例子列出所有比 '/etc/hosts' 旧的文件

# find -anewer /etc/hosts

示例8. 查找比某个文件修改时间新的所有文件

语法:

Syntax: find -cnewer FILE

下面例子会查找所有修改时间比 '/etc/fstab' 新的文件:

find -cnewer /etc/fstab

三、针对找到的文件执行操作

在这篇文章和之前的文章中,我们已经了解了各种 find 命令的用法。这这部分内容将介绍如何针对找到的文件执行各种操作,语法:

find <CONDITION to Find files> -exec <OPERATION> \;

OPERATION 可以是任何命令,比如:

  1. rm 命令,删除所找到的文件

  2. mv 命令,移动或重命名所找到的文件

  3. ls -l 命令,显示所找到文件的详细信息

  4. md5sum 命令

  5. 执行任何 Unix/Linux shell 命令

  6. 或者执行自己编写的 shell 脚本

示例9. 列出找到文件的详细信息

# find -mmin -60
./cron
./secure

# find -mmin -60 -exec ls -l {} \;
-rw-------  1 root root 1028 Jun 21 15:01 ./cron
-rw-------  1 root root 831752 Jun 21 15:42 ./secure

示例10. 仅在当前的文件系统中查找

如果希望仅查找根文件系统而不查找其他挂载分区的文件可以参考下面示例。这个示例会在根文件系统中查找 '*.log' 文件,如果已其他分区挂载,那么所有分区都会被查找:

# find / -name "*.log"

使用 xdev 选项可以指定 find 仅查找当前文件分区,下面是 xdev 选项的说明:

-xdev:不级联查找挂载其他分区的目录

下面命令仅会在当前文件系统中查找 '*.log':

# find / -xdev -name "*.log"

示例11. 在一个命令中使用更多个 {}

手册上的说明指出,只能使用一个 {} 示例,不过我们可以参考下面示例在一个命令中使用多个 {} :

# find -name "*.txt" cp {} {}.bkup \;

在一个命令中使用 {} 是可以的,不过在多个命令中使用这个是不行的,比如:

find -name "*.txt" -exec mv {} `basename {} .htm`.html \;

示例12. 在多个命令中是用多个 {}

我们可以使用 shell 脚本来模拟,比如下面 shell 脚本:

# mv "$1" "`basename "$1" .htm`.html"

然后在 find 命令中调用 shell 脚本:

find -name "*.html" -exec ./mv.sh '{}' \;

因此,对于任何原因,如果你想在命令中多次使用 {},可以像上面示例一样编写 shell 脚本进行模拟。

示例13. 重定向错误信息到 /dev/null

将错误信息重定向到 /dev/null 并不是一个好主意,尤其在 find 命令中做这个,不过如果你想做的话,可以参考下面示例:

find -name "*.txt" 2>>/dev/null

有些时候这样做也会带来一些好处,比如,如果你以普通用户身份从 '/' 开始查找 *.conf 文件,你会得到一堆 'Permission denied' 错误,比如:

$ find / -name "*.conf"
/sbin/generate-modprobe.conf
find: /tmp/orbit-root: Permission denied
find: /tmp/ssh-gccBMp5019: Permission denied
find: /tmp/keyring-5iqiGo: Permission denied
find: /var/log/httpd: Permission denied
find: /var/log/ppp: Permission denied
/boot/grub/grub.conf
find: /var/log/audit: Permission denied
find: /var/log/squid: Permission denied
find: /var/log/samba: Permission denied
find: /var/cache/alchemist/printconf.rpm/wm: Permission denied
[Note: There are two valid *.conf files burned in the "Permission denied" messages]

这时候就非常适合使用重定向错误到 /dev/null 了:

$ find / -name "*.conf" 2>>/dev/null
/sbin/generate-modprobe.conf
/boot/grub/grub.conf
[Note: All the "Permission denied" messages are not displayed]

示例14. 替换文件名中的空格为下划线

从互联网下载的多媒体文件的文件名大部分会包含空格,这对于 Unix/Linux 这类操作系统来说不是特别正规的文件名,我们可以使用下面命令来进行重命名:

$ find . -type f -iname “*.mp3 -exec rename s/ /_/g {} \;

示例15. 同时执行两个 find 命令

下面示例中,会先在所有文件中查找文件,将文件和目录的 setuid 信息保存在 /root/suid.txt,以及将超过 100M 的问价信息保存在 /root/big/txt

# find /    \( -perm -4000 -fprintf /root/suid.txt '%#m %u %p\n' \) , \
\( -size +100M -fprintf /root/big.txt '%-10s %p\n' \)
posted @ 2016-09-14 09:29  santo  阅读(458)  评论(0)    收藏  举报