Linux命令之find介绍

2016-11-12

(一)options

-d,-depth:二者作用相同,man手册和很多博客上都说它们的作用是:首先查找当前目录文件,然后再在其子目录查找。不过我自己实验了很多次,发现没什么效果。。。烦请高人指点~

-maxdepth:指定最大目录深度,也就是指定目录的几级子目录:1代表只是指定目录本身;2表示一级子目录;3代表“孙目录”,以此类推。。。

m@meng:~/patches/tmp$ find . -maxdepth 1 -name 'onlyme*'

./onlyme

./onlyme1

m@meng:~/patches/tmp$ find . -maxdepth 2 -name 'onlyme*'

find . -maxdepth 2 -name 'onlyme*'

./test/onlyme5

./test/onlyme.sh

./onlyme

./onlyme1

-mindepth:类似上面的-maxdepth,但是指定的是最小深度。比如指

定 2,那就是只搜索深度大于2的各级子目录,而不理会小于2的那些目录(小于2的就是指定目录本身),如下例: m@meng:~/patches/tmp$ find . -mindepth 1 -name 'onlyme*'

./test/onlyme5

./test/onlyme.sh

./onlyme

./onlyme1

m@meng:~/patches/tmp$ find . -mindepth 2 -name 'onlyme*'

./test/onlyme5

./test/onlyme.sh

-help:显示帮助信息,并退出。 -mount或-xdev:如果某个(子)目录是另一个文件系统的挂载点,则跳过该目录。

-daystart:先看man手册的说法:Measure times (for -amin, -atime, -cmin, -ctime, -mmin, and -mtime) from the beginning of today rather than from24 hours ago. 看来这个选项只影响那些跟时间有关的test,而且改变了时间的计算方式,即不再从当前时刻开始计算,而是从每天的0:00开始计算。前面说过,-atime n,这个n并不代表实际的“一天”,而是指24小时;但是加上-daystart这个选项之后,就可以真的代表“一天”了,因为这时就是从每天的0:00开始计时的,看下面的例子:

m@meng:~/patches/tmp$ date

2015年 07月 12日 星期日 00:13:47 CST

m@meng:~/patches/tmp$ stat new

最近访问:2015-07-12 00:10:15.707908310 +0800

最近更改:2015-07-12 00:10:15.707908310 +0800

最近改动:2015-07-12 00:10:15.707908310 +0800

m@meng:~/patches/tmp$ stat test

最近访问:2015-07-11 23:42:25.064527595 +0800

最近更改:2015-07-06 23:57:45.095385673 +0800

最近改动:2015-07-06 23:57:45.095385673 +0800

m@meng:~/patches/tmp$ find -atime 0

.

./test

./new

m@meng:~/patches/tmp$ find -daystart -atime 0

.

./new

这就很显然了,在没有加上-daystart这个选项之前,-atime 0指的是从当前这一刻开始,往前的24小时之内,如果某个文件被访问过,则匹配;但是加上-daystart之后,-atime 0表示今天被访问过的文件才会匹配。同理-atime 1表示昨天(即7/11 0:00 ~ 7/11 23:59)被访问过的文件才会匹配。

这个选项的作用可以简单归纳为:化零为整。

(二)actions

-delete:找到匹配的文件之后,将其删除。man手册上提到:Use of -delete automatically turns on the -depth option,不过我还没搞懂这个-depth到底有什么卵用。。 -print:这个是默认的action,即没有指定任何action的时候其实就是使用了这个-print,但是指定了另一个action的时候,就必须显式加上-print才有效果。它把每个匹配的文件打印到标准输出上,每行一个文件。这意味着,-print在打印的时候,每个文件末尾添加了一个换行符。

但是这个换行符是为了浏览方便,有时会造成一些麻烦,比如使用管道的时候;如果想省略这个换行符,可以用-print0来代替,如下: m@meng:~/patches/tmp$ find -daystart -atime 0 -print

.

./new

m@meng:~/patches/tmp$ find -daystart -atime 0 -print0

../newm@meng:~/patches/tmp$

所以,如果只是想在终端观察输出,没有必要使用-print0,-print就足够了。

-print还有一个变种是-printf,类似于C语言中的printf函数,进行格式化输出,暂时不研究了,有太多格式。

-ls:类似于ls命令的-dils选项组合,如下: m@meng:~/patches/tmp$ find -daystart -atime 0 -ls

7478778 4 drwxrwxr-x 3 m m 4096 7月 12 00:10 .

7478967 0 -rw-rw-r-- 1 m m 0 7月 12 00:10 ./new

m@meng:~/patches/tmp$ ls -dils new

7478967 0 -rw-rw-r-- 1 m m 0 7月 12 00:10 new

换了一种更详细的输出而已。

f系列,即-(fls/fprint/fprint0/fprintf) file,这几个action与没有开头f的那几个action是非常相似的,只是不再把结果打印到标准输出,而是输出到文件file中。

-exec command ;与-exec command {} +

-exec本身其实只是在find执行完之后执行另一条命令,我之前以为-exec类似于管道,find找到的文件会直接被command处理,结果不是这样;若想要达到管道的效果,需要在 command后面添加“{}”,它代表前面找到的文件。

然后是语法问题:command后面没有“{}”时,必须要以一格空格和一个分号结尾;command后面有“{}”时,可以使用前面那种结尾方式,也可以使用一个空格和一个“+”结尾;

为了防止shell本身的扩展,分号需要转义,要么前面添加反斜线,要么用引号括起来;同理“{}”最好也用引号保护起来。

m@meng:~/patches/tmp$ find . -name new -print -exec cat onlyme1 ;

./new

haha

m@meng:~/patches/tmp$ find . -name new -print -exec cat onlyme1 +

find: 缺少“-exec”参数

m@meng:~/patches/tmp$ find . -name new -print -exec cat {} ;

./new

hello

m@meng:~/patches/tmp$ find . -name new -print -exec cat {} +

./new

hello

m@meng:~/patches/tmp$ find . -name new -print -exec cat {} ';'

./new

hello

m@meng:~/patches/tmp$ find . -name new -print -exec cat {} ";"

./new

hello

第一个例子说明command和find之间可以是完全独立的;第二个说明command后面没有“{}”时只能以分号结尾;后面几个例子说明了有“{}”时的结尾情况。

-execdir command ;和-execdir command {} +

与上一对选项类似,只是-exec后面的command是在当前目录执行的;而-execdir是在匹配文件所在子目录中执行的。我们使用pwd命令测试一下:m@meng:~/patches/tmp$ ls

magic.mgc new onlyme onlyme1 test

m@meng:~/patches/tmp$ ls test/

onlyme5 onlyme.sh

m@meng:~/patches/tmp$ find . -name onlyme.sh -exec pwd ;

/home/m/patches/tmp

m@meng:~/patches/tmp$ find . -name onlyme.sh -execdir pwd ;

/home/m/patches/tmp/test

文件onlyme.sh在子目录test中,find在找到它之后执行pwd命令;但是-exec和-execdir的结果是不同的。

-ok与-okdir

与-exec和-execdir是基本相同的,只是在执行之前会先询问一下用户。 -prune

if the file is a directory, do not descend into it. 就是说,如果某个目录匹配了,那么就不再进入这个目录进行搜索。m@meng:~/patches/tmp$ find . -name 'test*'

./test

./test/test1

m@meng:~/patches/tmp$ find . -name 'test*' -prune

./test

我们看到,匹配 -name ‘test*’的包括test子目录本身以及test目录下的test1文件;但是加上-prune选项之后,就不在进入到test目录中进行搜索了,因为test目录本身也是一

个匹配项。-prune经常配合-path用来排除某些子目录。

-quit

立即退出,-quit之后的命令将不再执行。如下:m@meng:~/patches/tmp$ find . -name new -print -exec cat {} ";"

./new

hello

m@meng:~/patches/tmp$ find . -name new -print -quit -exec cat {} ";"

./new

m@meng:~/patches/tmp$ find . -name new -print -exec cat {} ";" -quit

./new

hello

m@meng:~/patches/tmp$ find . -name new -quit -print -exec cat {} ";"

m@meng:~/patches/tmp$

(三)逻辑运算

先扔一段man手册的信息:

The expression is made up of options (which affect overall operation rather than the processing of a specific file, and always return true),tests

(which return a true or false value), and actions (which have side effects and return a true or false value), all separated by operators.

-and is assumed where the operator is omitted.

If the expression contains no actions other than -prune, -print is performed on all files for which the expression is true.

这就是说,expression的三个组成部分其实都是布尔表达式,而表达式都是有值的,不是true就是false。手册说,options的值永远是true;而其他两者的值可true可false。

这样,就会有逻辑运算,其实主要是test之间的运算,因为一个expression里面可以有多个test,这些test之间可以进行与、或、非运算。

比如上篇文章中的例子:

m@meng:~/patches$ find . -path ./tmp -o -name onlyme

./tmp

./tmp/onlyme

至此,find命令的基本用法完毕~好累。上面的总结肯定有不完善的地方,我会再以后慢慢补充慢慢纠正的。

更多相关阅读

最新发布的文章