曲径通幽论坛

 找回密码
 立即注册
搜索
查看: 6347|回复: 0
打印 上一主题 下一主题

十八个 find 命令查找文件的技巧

[复制链接]

4918

主题

5880

帖子

3万

积分

GROAD

曲径通幽,安觅芳踪。

Rank: 6Rank: 6

积分
34387
跳转到指定楼层
楼主
发表于 2012-2-26 02:01:40 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
下面演示几个 find 命令查找文件的技巧。

1. 使用 -iname 选项忽略文件名的大小写
假设当前目录下有这么两个文件:
$ ls BEYES.txt ./level2/beyes.txt
BEYES.txt./level2/beyes.txt
这两个文件位于不同的目录,文件名只是在大小写上不同,如果希望同时找到这两个文件,可以使用 find 命令的 -iname 选项:
$ find -iname "beyes.txt"
./BEYES.txt
./level2/beyes.txt

2. 通过 -mindepth 和 -maxdepth 选项指定目录深度查找文件
有时候查找文件大可不必让 find 命令递归到最底层目录,这样会造成查找的负担较大,假如我们大概知道文件所在目录的大概深度,我们可以通过 -mindepth 和 -maxdepth 这两个选项来指定查找的最小目录深度和查找的最大目录深度。比如有这两个文件:

如果指定 -maxdepth 的值为 1 我们就无法找到 /selinux/class/passwd/perms/passwd 这个文件,如:
# find /selinux/ -maxdepth 1 -name passwd
#无输出

又有:
# find / -maxdepth 3 -name passwd
/selinux/class/passwd嬀挀漀氀漀爀=#7030a0]#这里的 passwd 是个目录
/etc/passwd
/etc/pam.d/passwd
/usr/bin/passwd
... ...
同样只能查找到自根目录其 3 层目录深度以内的所有名为 passwd 的文件。

3. 通过 -exec 选项对查找到的文件执行相关命令
我们可以通过 -exec 选项对查找到的文件执行相关的命令,比如找到相关文件后就计算它们的 MD5 值:
$ find -iname "beyes.txt" -exec md5sum {} \;
d41d8cd98f00b204e9800998ecf8427e./BEYES.txt
d41d8cd98f00b204e9800998ecf8427e./level2/beyes.txt
上面 {} 是找到的文件的一个替代符号,而后面的反斜杠是转义字符,因为 -exec 后面所执行的命令在遇到分号时标明命令结束,所以这里用反斜杠对分号转义是为了保持分号的原来面貌,而不要 shell 对其另有解释。

又如将找到的文件重命名:
$ find -iname "beyes.txt" -exec mv {} {}.bak \;$ find -iname "beyes.txt.bak"
./BEYES.txt.bak
./level2/beyes.txt.bak


4. 使用 -not 选项进行反匹配查找
默认情况下都是正向匹配查找,但通过 -not 选项可以反匹配查找,如:
[beyes@beyes find]$ ls
BEYES.txt.bak氀攀瘀攀氀2琀攀洀瀀.txt琀洀瀀.txt
[beyes@beyes find]$ ls level2/
beyes.txt.bak
$ find -not -iname "beyes.txt.bak"
.
./temp.txt
./level2
./tmp.txt

5. 通过节点号查找文件
每一个文件都会有一个对应的节点号,也可以使用该号码来识别文件。下面举例一种稍微特殊的情况,先创建两个文件:
$ touch "tmp.txt"
$ touch "tmp.txt "
注意,上面创建的第 2 个文件比第 1 个文件的末尾多了一个空格,虽然在 ls 命令下看似一样,但实际上不是同一个文件:
$ ls tmp*
tmp.txt琀洀瀀.txt
这时,我们可以通过 ls 的 -i 选项列出这两个文件的节点号:
$ ls -i1 tmp*
132546 tmp.txt
132561 tmp.txt
上面的 -i 选项后的 1 表示要求一次输出 1 行。

我们可以通过 find 的 -inum 选项来指定文件的节点号来查找文件:
[beyes@beyes find]$ find -inum 132561 -exec mv {} new_tmp.txt \;
[beyes@beyes find]$ ls *.txt
new_tmp.txt琀洀瀀.txt

使用节点号来查找文件可以很好的删除一些名字乱码了的文件。

6. 使用 -perm 选项查找相应权限的文件
假设某个目录下有如下文件(注意各个文件的权限):
$ ls -l
total 0
-rwxrwxrwx. 1 beyes beyes 0 Feb 26 01:42 all_perm.txt
-rw-r--r--. 1 beyes beyes 0 Feb 26 01:43 temp1.txt
-rwxr-xr-x. 1 beyes beyes 0 Feb 26 01:44 temp2.txt
-rw-------. 1 beyes beyes 0 Feb 26 01:44 temp3.txt
-----w----. 1 beyes beyes 0 Feb 26 01:45 temp4.txt
现在查找所有的用户组含有写权限的文件:
$ find . -perm -g=w -type f -exec ls -l {} \;
-rwxrwxrwx. 1 beyes beyes 0 Feb 26 01:42 ./all_perm.txt
-----w----. 1 beyes beyes 0 Feb 26 01:45 ./temp4.txt[/qutoe]

查找所有权限中只有用户组写权限的文件:
[quote]$ find . -perm g=w -type f -exec ls -l {} \;
-----w----. 1 beyes beyes 0 Feb 26 01:45 ./temp4.txt

在上面的两种查找中,其区别在于 g 的前面一个是有一个 '-’ 符号,而另外一个没有的。

也可以直接使用八进制的权限形式查找:
$ find . -perm 600 -type f -exec ls -l {} \;
-rw-------. 1 beyes beyes 0 Feb 26 01:44 ./temp3.txt

7. 使用 -empty 选项查找空文件

找到家目录里的所有空文件(包括空目录):
$ find ~ -empty
/home/beyes/Downloads
/home/beyes/.mozilla/plugins
/home/beyes/.mozilla/extensions
/home/beyes/Templates
/home/beyes/Documents
/home/beyes/temp/find/temp1.txt[/qutoe]

找出当前目录下非隐藏的空文件(查找目录最大为 1 层):
[quote]$ find . -maxdepth 1 -empty -not -name ".*"
./Downloads
./Templates
./Documents
./Videos
./Pictures
./Public
./Desktop
./Music

8. 查找尺寸最大的前 5 个文件
$ find . -type f -exec ls -s {} \; |sort -n -r |head -5
340 ./os/linux/sta_ioctl.o
316 ./common/mlme.o
296 ./common/cmm_info.o
292 ./common/cmm_wpa.o
268 ./os/linux/rt_linux.o
上面,ls 命令的 -s 选项是以块为单位来列出文件的大小,340 即表明该文件的大小为 340 个块,一般情况下,每个块的大小为 4096 字节 ,看文件系统的块大小的几种方法可参考:《查看文件系统块的大小》 。在 sort紀令中,-r 选项是反向输出,-n 选项表示以“纯数字”来排序。当然,要以正序排序,那么就不需要 -r 选项,因此要查找尺寸最小的前 5 个文件可用命令如下:
$ find . -type f -exec ls -s {} \; |sort -n |head -5
4 ./common/eeprom.c
4 ./include/action.h
4 ./include/ags.h
4 ./include/br_ftph.h
4 ./include/chip/rt2870.h
上面的 5 个文件的块大小均为 4K ,也就是说它们的实际大小不超过 4K,只需要一个块就可以存储。

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

查找当前目录下普通文件:
$ find . -type f

查找当前目录下所有子目录:
$ find . -type d

查找 socket 文件:
$ find . -type s

查找当前目录下所有隐藏文件:
$ find . -type f -name ".*"

查找当前目录下所有隐藏目录:
$ find . -type d -name ".*"

10. 使用 -size 选项按照文件大小来查找文件

查找当前目录下所有大于 10M 的文件:
$ find ~ -size +10M
/home/beyes/kernel-2.6.38.6-26.rc1.fc15.i686.rpm
/home/beyes/kernel-2.6.38.6-26.rc1.fc15.src.rpm
/home/beyes/rpmbuild/SOURCES/linux-2.6.38.tar.bz2

类似,如果查找所有小于 10M 的文件,那么使用命令:
$ find ~ size -10M

如果是严格匹配一个大小的话,那么给出的尺寸面前不添加 "+" 或 “-” 符号,如:
$ find ~ size 10M

11. 按照修改时间来查找文件
当前目录下有以下几个子目录:
$ ls -lrt
total 40
drwxr-xr-x. 2 beyes beyes 4096 Dec 26 08:48 bolog
drwxr-xr-x. 2 beyes beyes 4096 Dec 30 23:48 3366
drwxr-xr-x. 2 beyes beyes 4096 Jan3 23:12 mywork
drwxr-xr-x. 2 beyes beyes 4096 Jan5 10:37 mytest
drwxr-xr-x. 2 beyes beyes 4096 Jan5 23:11 tianya
drwxr-xr-x. 4 beyes beyes 4096 Jan7 12:57 39net
drwxr-xr-x. 2 beyes beyes 4096 Jan8 22:44 moko
drwxr-xr-x. 3 beyes beyes 4096 Feb 23 23:10 meinv
drwxr-xr-x. 2 beyes beyes 4096 Feb 24 13:37 moko_qunet
drwxrwxr-x. 2 beyes beyes 4096 Feb 27 10:43 netease[/qutoe]
现在假设要查找修改时间比 Feb 23 23:10 要新的目录:
[quote]$ find -type d -newer meinv
.
./moko_qunet
./netease
上面使用了 -newer 选项,即要求查找要比当前所给出的文件的修改时间更靠前的所有文件。

12. 使用别名缩短查找时间
如果要经常查找某一文件,找到后并打算将其删除,那么我们可以考虑先建立一个查找命令的别名,这样在下次查找时只要输入别名即可,而不要每次都输入较长的查找指令。比如:
$ touch TEMP.TXT
$ ls TEMP.TXT
TEMP.TXT
$ alias deltmp="find . -iname TEMP.TXT -exec rm {} \;"
$ deltmp
$ ls TEMP.TXT
ls: cannot access TEMP.TXT: No such file or directory

13. 找到所有大于某尺寸的文件然后将它们全部删除
这种情况比较适合删除那些较大的,且不再需要的临时文件或压缩文件:
$ find / -type f -name "*.tar.gz" -size +1G -exec rm -i {} \;
上面找到所有大于 1G 的 .gz 压缩文件并将它们删除,删除时会提示确认是否要真正删除。


14. 使用 -path 选项进行路径里的匹配
-path 选项后跟一匹配项(-path pattern),如果查找的目录下的所有路径中只要含有匹配 pattern 的就认为被找到。这里,路径中的匹配不但可以是最终文件名的匹配也可以路径中某一个子目录的匹配,如:
root@bt:~# find . -path "*sh"
./.kde/share/apps/ksplash
./.kde/share/apps/ksplash/Themes/bt5-Ksplash
./shell/tmp.sh
./.ssh
./temp.sh
./.wine/drive_c/MinGW/libexec/gcc/mingw32/3.4.5/install-tools/fixinc.sh
./.gem/ruby/1.9.2/doc/typhoeus-0.3.3/ri/Typhoeus/NormalizedHeaderHash
./.gem/ruby/1.9.2/doc/typhoeus-0.2.4/ri/Typhoeus/NormalizedHeaderHash
./tmp.sh
./delay.sh
./.local/share/Trash
./debug.sh

15. 使用 -regex 进行正则匹配查找
root@bt:~# find . -regex ".*\(\.sh\|\.txt\)$"
./.kde/share/apps/ksplash/Themes/bt5-Ksplash/1600x1200/description.txt
./shell/tmp.sh
./temp.sh
./.subversion/README.txt
./.wine/drive_c/MinGW/libexec/gcc/mingw32/3.4.5/install-tools/fixinc.sh
./.gem/ruby/1.9.2/gems/mime-types-1.16/History.txt
./.gem/ruby/1.9.2/gems/mime-types-1.16/README.txt
./.gem/ruby/1.9.2/gems/mime-types-1.17.2/Manifest.txt
./tmp.sh
./delay.sh
./debug.sh
./.mozilla/firefox/nq474mcm.default/urlclassifierkey3.txt
如果将 -regex 写成 -iregex 就表示该正则匹配对大小写不敏感。

16. 使用时间查找
和文件相关的时间有 3 个:

访问时间(Access time)(-atime) :最近一次访问文件时产生的时间戳

修改时间(Modification time)(-mtime):最近一次文件内容被修改时产生的时间戳

改变时间(Change time)(-ctime):最近一次文件的元数据(如权限或者所属)被修改时产生的时间戳

找出当前目录下所有在过去 7 天内被访问的普通文件:
find . -type f -atime -7 -print

找出当前目录下所有过去第 7 天所被访问的普通文件:
find . -type f -atime 7 -print

找出当前目录下所有 7 天内所被访问的普通文件:
find . -type f -atime +7 -print

注意,上面的 -atime 这些参数的时间是以天数计算的,而相应的 -amin,-mmin,-cmin 则是用分钟来计算。

17. 使用 -prune 选项忽略指定目录
往往有些时候,我们在查找一个目录时,希望从中剔除掉某个包含不希望查找的子目录(比如事先知道这个子目录里有一些垃圾信息),那么此时可以使用 -prune 选项。

先查找当前目录下所有 .sh 文件:
root@bt:~# find . -name "*.sh"
./shell/tmp.sh
./temp.sh
./.wine/drive_c/MinGW/libexec/gcc/mingw32/3.4.5/install-tools/fixinc.sh
./tmp.sh
./delay.sh
./debug.sh
现在假设我在查找时,我希望忽略掉 shell 这个子目录,那么可以如下使用:
root@bt:~# find . \( -name "shell" -prune \) -o \( -name "*.sh" -print \)
./temp.sh
./.wine/drive_c/MinGW/libexec/gcc/mingw32/3.4.5/install-tools/fixinc.sh
./tmp.sh
./delay.sh
./debug.sh
上面 -o 选项是“或”的意思,当 \( -name "shell" -prune \) 这个表达式为假时,后面的 \( -name "*.sh" -print \) 表达式才得以执行。也就是说,当第一个表达式为真时,即匹配了查找进程已经找到 shell 这个子目录,然后只是简单的 -prune 忽略掉它,此时并不会执行后面的语句,否则就会将 shell 子目录中的 sh 文件打印出来。

18. -print0 让输出的全文件名以 '\0' 结尾
-print0 选项以输出的全文件名以 '\0' 结尾,这样的输出结果通过管道后可以方便一些工具正确处理。比如一个文件的文件名含有空格符,那么如果不用该选项可能会导致一些其它工具(如 xargs)对输出结果产生错误的解析。更多详细内容可参考:http://www.groad.net/bbs/read.php?tid-498.html
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|曲径通幽 ( 琼ICP备11001422号-1|公安备案:46900502000207 )

GMT+8, 2024-5-19 19:07 , Processed in 0.062495 second(s), 22 queries .

Powered by Discuz! X3.2

© 2001-2013 Comsenz Inc.

快速回复 返回顶部 返回列表