Linux下4.5个关于查找和修改的命令总结———find

用了Linux也有蛮久的了,但是还是一个新手的样子,对好多的东西还不是太熟悉,一个伪linuxer,之前用的也不是太多,简单的make,几个命令.实习工作都是后台开发的职位,对*nix系统接触比较多,最发觉cmd line有趣,故,总结一下,新手学习,老手指点.

linux中让我觉得最有用的也是最high的就是强大的其中的查找功能体系,find,grep,sed,awk四个命令组合可以建造无限的可能,xargs就算0.5个吧.对于这个几个命令google一下好多好多教程,直接man一下会有非常详细解释,但是细看那些教程无非就是直接把man中的英文内容翻译成中文然后贴出来,对于一个初学者来说是没有什么重点可言的,让人觉得不知道看那里好.有一些实例并且对一些参数的使用频率和实用程度进行排序介绍,让我们更容易了解这个命令的用法.

OK,说到查找那就不得不说find,意思就是各种找,只有你想不到的,没有它找不到的.

格式find [-H] [-L] [-P] [path…] [expression]

-name

简单例子是 find ./ -name '*.log' 意思找出当前目录下文件名后缀是log的文件,这个是包含子目录的,也就是说可以找到当前目录中所有文件和目录中的文件,如果不想查找子目录的文件怎么办?用-depth指定查找深度,这个下面会讲到.

1. -name 按照文件或目录的名字查找,后面跟着的参数是可以是正则表达式,当然这里有些比较特殊的地方.

-name后边的正则表达式是不包含通配符点'.'和目录的表示符斜杠'/'的,只接受通配符'*','?','[]'.也就是说如果想找./php-5.6.0/config.log用find ./ -name '*/*.log'是查找不来的,因为-name只匹配文件或者是目录的名字部分,并不匹配路径中包含的字符,也就是用它只会匹配config.log部分而不会匹配前面的./php-5.6.0/部分.若想匹配路径中的字符例如前缀是php-的目录下的所有.log文件,可用find ./ -path '*php-*/*.log'

还有一个值得注意的地方是,这里的正则表达式并不接受行头'^'和行尾'$'符,它把它们识别为普通字符,所以'php-*'就会被解释为以php-开头的字符,相当于'^php-*',而'php-'则会被解释为只包含'php-'这个字符串,相当于'^php-$',所以find中的正则表达式并不像grep,sed,awk中的那样标准(这样的话好像它只能算是匹配的表达式吧^_^),这里是有踩过坑的…..

上面说了-name命令是会匹配文件和目录的,想像一下这种情况

.

├── config.log

└── xxx

    └── config

        ├── a.log

        └── config.log

用find ./ -name '*config*'的命令会匹配得到

./xxx/config

./xxx/config/config-1.0.log

./config.log

在某些情况下我们只想找到包含conifg的目录而这个目录中的文件我们并不关心,可以加上-prune

$ find ./ -name '*config*' -prune

./xxx/config

./config.log

再比如我们只查包含config的文件目录我们并不需要,加上type f参数,f这里指的是只匹配文件,type选项还有很多参数,自己man一下就可以找到了

time

查找log文件的时候find命令是很常用的,比如我有30天内的log记录,由于写log的时候限制最大文件只能有2M,所以每个log文件创建和修改的时间都不是固定的,在成百上千个文件中查找某天甚至某个时刻修改过,创建过或者是被访问过的文件用find命令是很方便的

我们都知道有-mtime和-mmin选项,前面的m表示modify,指修改时间,还有-atime,-amin,-ctime和-cmin,a表示access time,c表示change time,他们用法都是一样

用法是find ./ -mtime 1,-mtime表示按24小时查找,-mmin表示按分钟查找,如果现在时间是10月3日16:40的话,这句话的意思是查找10月1日16:40到10月2日16:40之间被修改过的文件,转换成数学式子就是从now-(n+1)*24h到now-n*24h,n是可以等于0的哦

OK,想查询now-n*24h到now时间段内修改过的文件可以用find ./ -mtime -n

查询now-(n+1)*24h之前被修改过的文件则用find ./ -mtime +n

-mmin也是一样的原理

好了,现在我们想查找某个时间段内的被修改过的文件是办法了,但是你是否觉得这样好麻烦呀..比如想要查询9月15日16:05到9月18日9:30内修改过的文件,我还得想一想..9月15号离现在是几天?9月18号离现在又是几天?想啊想~想啊想~那最后得出的命令是

find ./ -mtime -18 -mtime +14

运行一看,好像不太对呀…原来现在的时间是10月3日16:40,'-mtime -18'所得的时间是9月15日16:40,而'-mtime +14'所得的时间是9月18日16:40..这两个时间段好像有点误差- -!

如果想更准确更直观的找一个时间段内的文件肿么办呢?查看manual里有一个-newerXY选项,google一下发现,用的是-newermt,它接受'yyyy-mm-dd hh:MM:ss'的时候格式,以上的查询就可以写成

find ./ -newermt '2014-09-15 16:05' ! -newermt '2014-09-18 09:30'

-newermt表示在这个时间之后被修改过的,加一个!就不在这个时间之后被修改过的,所以时间区间是(2014-09-15 16:05, 2014-09-18 09:30],当然也有-newerct和-newerat,表示change时间和访问时间的

用-newermt有一个局限性,那就是只有4.3.3及以上的find的版本才支持,可用find -version查看下自己find的版本,可是公司的服务器Linux版本要都比较老是4.2.2版本的,那应该肿么办呢 ?

可以发现还有一个-newer file的选项,可以用比较文件的时间来确定时间范围,那怎么创建一个指定时间的文件叫呢?然后是touch命令啦,注意文件的change time是不能修改的,如果要查找有关change time的话只能用-ctime的方式了

先创建两个文件,他们的modified time 分别是2014-09-15 16:05和2014-09-18 09:30,再用-newer选项判断时间区间

touch -t 201409151605 start

touch -t 201409180930 end

find ./ -newer start ! -newer end

用的方式和-newermt一样

-exec

当我们在执行find命令之后想要对查询的结果进行一些其它的操作,例如列出文件详细信息,删除文件等等,可以用|+xargs,也可以用-exec选项

通过manual文档得知在用-exec选项的时候我们用一对大括号'{}'来代替一条查询结果,如果查询结果有多条,则会逐条传入,有点类似于xargs,如果不了解xargs的话接下来的几篇博文会介绍到.当-exec遇到分号';'的时候,会不再向;之后的选项传递参数,而-exec遇到反斜杠'\'时,再表示-exec选项中的命令执行完成.所以在找出文件并且删除的时候可以像以下这样写

find ./ -name '*config.log' -exec rm {} \;

这里要注意的是,'{}'和'\;'之间是是有一个空格隔开的,-exec后可以写shell命令


最后说一点是,如果一个目录软链接到其它地方的话,find命令默认情况下是不会查找这个下的文件的,需要加上参数-L,并且必须写在find后边,像这样

find -L ./ -name '*config.log'

好了,find命令就写这么多,都是血与泪的教训….还有很多的参数manual里写的都比较清楚,一看就知道是啥意思了,这里就不再细说了

下一篇要讲xargs还是grep呢?

Leave a Reply

Your email address will not be published. Required fields are marked *