Find命令实战

话说linux中我最常用的几个命令就是awk, grep, vim, find,今天我们就来详细看下find命令的使用

先来一个简单例子:
find . -name "*.java"  # 递归查找当前目录下所有java文件

其中:
[b]. [/b]表示查找路径为当前目录(你也可以指定为其他工程目录,譬如:~/workspace/login)
-name 表示搜索的目标文件名或目录名(允许使用shell通配符)

通常上述命令已经能够完成你日常工作需求的80%,但是要想完成另外的20%,你必须再深入了解下find命令...

现在假设你需要查找Test.java 和 TEST.java这两个文件,这时候你该如何做?
也许你会find . -name "Test.java" 和 find . -name "TEST.java" 执行两遍

虽然这样做结果正确,但是有没有更简单的方式呢? 答案,自然有
find . -iname "test.java" 	# -iname 与-name参数含义一样,但是忽略大小写

发现没,是不是更优雅了...

现在我们更进一步,假设我们需要列出~/scripts目录下所有名为study的文件该如何做呢?

在不了解find命令之前,也许你需要使用shell for循环来递归遍历目录,然后对每个找到的study判断是否为文件(有可能是名为study的目录),若确实是文件则输出. 说了这么多,这个方式真的是繁琐异常,但是如果你了解find命令,那么[b]just one line![/b]
find ~/scripts -type f -name "study"

其中-type参数用来指定搜索的目标类型,f表示普通文件,-type还有其他常用的参数值:f-文件, d-目录

现在你已经了解了:
1.如何指定find搜索路径
2.如何指定find搜索的目标类型(-type)
3.如何指定find搜索的文件名或是目录名(-name / -iname)

真是不少东西了呢,不过我们要继续前行,find命令还有很多很有用的参数。

find命令默认是递归搜索,它的搜索算法应该是我们常说的深度优先遍历(可以通过指定-depth参数指定采用广度优先遍历算法),但是有时候我们希望仅在当前目录搜索,或是能够指定递归查找的深度,这时候该如何做呢? 两个字简单

-maxdepth: 指定递归查找时的目录最大深度,若为1,表示仅在当前目录查找
-mindepth: 指定递归查找时的目录最小深度

现在我们看两个例子(先不要尝试去运行):
find . -name "*.java" -maxdepth 3
find . -maxdepth 3 -name "*.java"

这两个命令看似没有什么差异,但是运行效果确相差万里(特别是当文件很多目录又非常深时),或者在有的机器上第一种形式根本无法运行,原因为什么呢?

因为第一个命令它首先会找出所有java文件,然后再筛选出满足深度条件的文件,这样效率非常非常之低,而第二个命令则仅仅是在1-3层目录下搜索目标文件,而没有对整个文件树进行递归遍历,所以效率很高.

在我的机器上执行第一种命令,弹出以下警告:
find: warning: you have specified the -maxdepth option after a non-option argument -name, but options are not positional (-maxdepth affects tests specified before it as well as those specified after it). Please specify options before other arguments.


好了,你现在你的手上又多了两把利器 -maxdepth 和 -mindepth(这个两个参数,可以提高你的查找效率以及zhuangbility)

find命令还几个很有用的参数
-mtime: 文件内容最后修改时间
-atime: 文件最后访问时间
-ctime: 文件meta信息最后修改时间(譬如文件权限)

这几个参数后面需要跟一个整型值使用,eg:
find . -mtime 1  -name "*.java"  	# 在当前目录下递归查找距离现在整1天修改的java文件
find . -mtime -1 -name "*.java" # 在当前目录下递归查找1天内修改的java文件
find . -mtime +1 -name "*.java" # 在当前目录下递归查找1天前修改的java文件

如果你需要查找某个时间段内的修改的文件,这些命令就非常有效了(搞运维的同学应该经常使用)

说了这么多参数(-name, -iname, -type, -mindepth, -maxdepth, -mtime等等),想必你对find命令已经有所了解,
现在我们来看看find命令的一个好基友----xargs

通常我们需要对查找出来的文件执行某些action,譬如我想查找某个工程目录下所有使用到StringUtils的java文件,这时候该怎么办呢?

方法1我们可以使用eclipse的搜索,方法2我们可以编写脚本,方法3 [b]just one line ...[/b]

find ~/worksapce/project -name "*.java" | xargs grep "StringUtils"  

其中:
find ~/worksapce/project -name "*.java" 将会在家目录下workspace/project中递归查找所有java文件
xargs grep "StringUtils" 表示在文件中(find命令查找出的结果集)查找含有StringUtils字样的文件

也许有人一开始会这样写:find ~/worksapce/project -name "*.java" | grep "StringUtils"
这个命令执行将不会产生任何结果,而原因就是因为没有使用xargs!

现在我们就来说说xargs:xargs是用来把输入流转化为参数的命令(默认把输入流中的空白字符譬如"\n"(换行)替换成" "(空格))
$ cat test 
a
b
c
d
e
$ cat test | xargs
a b c d e

find命令将查找出的每一个文件名或目录名默认用"\n"分割,然后通过管道 | 作为输入流传递给grep命令,但是grep命令要求输入流必须是参数的形式,譬如:grep "target" file1 file2 所以必须使用xargs重新将输入流转换为参数

说到这里,一些比较严谨的同学也许会说,这样的命令:find ~/worksapce/project -name "*.java" | grep "StringUtils" 是不严谨,不安全的(这里还谈不上不安全,毕竟只是一个grep命令,但要是变成xargs rm -rf 那就危险了),原因就是find命令默认用"\n"分隔结果列表,而xargs会把"\n"转化成空格,所以当文件路径或者文件名含有"\n"这些字符时,就会被错误替换,这时候你在执行个rm -rf ,[b]哦, 卖糕的...[/b]

所以我们应该养成好习惯,这样写
find ~/worksapce/project -name "*.java" -print0 | xargs -0 grep "StringUtils"

-print0用'\0'(空字符)分隔结果列表,xargs -0 只会将'\0' 替换成空格,这样就不会出现刚才所说的问题了....


关于find命令,我就说到这里,赶紧尝试吧...
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值