Contents
find 是 Unix 系统里面最强大和最有用的实用程序之一。他可以匹配文件名称、 类型以及修改时间等并对匹配到的文件执行相关操作。事实上,很多时候,find 都不是单纯用来查找文件的。如果仅仅要查找文件,通常用一个更快速的 locate 工具。
使用简介
find path operators
path
是指定一个或者多个 find 将在其中进行查找的目录。而 operator
可以
有很多选择,比如:
- -name filename
-
查找匹配
filename
的文件。 - -perm mode
- 查找指定权限的文件,文件权限必须以八进制形式给出。
- -type c
-
查找指定类型的文件,
c
可以是代表普通文件的 'f' 、代表块设备的 'b' 或者 代表软链接的 'l' 等。 - -user name
-
查找属于用户
name
的文件。name
可以通过用户名或者用户 id 来指定。 - -group name
-
查找属于组
name
的文件。name
可以通过组名称或者组 id 来指定。 - -size n
-
查找
n
块那么大的文件,每一块通常是 512 字节。+n
表示大于n
块,而nc
表示n
个字符那么长。 - -inum n
-
查找 inode 号为
n
的文件。 - -atime n
-
查找
n
天前访问过的文件。+n
表示``超过n
天''而-n
表示``小于n
天'' 。 - -mtime n
-
和
-atime
类似,不过检查文件内容被修改的时间。 - -ctime n
-
类似于
-atime
,不过检查 inode 状态上一次被改变的时间。 - -newer file
-
查找修改时间比
file
要新的文件。
可以把多个 operator
组合起来:
- operator1 -a operator2
-
查找满足
operator1
和operator2
的文件。事实上,-a
是可以省略的,因为 他是operator
之间的默认连接关系。 - operator1 -o operator2
-
查找满足
operator1
或者operator2
的文件。 - !operator
-
查找不满足
operator
的文件。 - \( expression \)
-
把一些东西组合起来当作一个单元来看待。这儿的
\
主要是用于转义,以免被 shell 解释掉括号了。
另外,还有一些 operator
用于告诉 find 如何对待找到的文件。
- 在标准输出打印文件名。这通常是默认的操作。
- -ls
-
用一个类似与
ls -l
的格式列在标准输出出文件名。 - -exec command
-
执行
command
。使用{}
来表示匹配到的文件名。command
必须以\;
来标记 结束。如find . -name '*.o' -exec rm -f {} \;
。 - -ok command
-
和
-exec
一样,不过他在执行命令之前会先向你询问是否要执行。
查找特定名称的文件
在匹配文件名的时候可以使用通配符。比如:
find . -name '*.o' -print
注意 -name
选项指定的通配符只是匹配文件名的部分,而不管路径部分,如果
要指定路径部分的匹配模式,可以用 -wholename
或者 -path
选项。如果是要
跳过某个目录以及其子目录的所有文件,可以使用 -prune
选项,而不是检查那
个目录下面的所有文件,例如:
find . -wholename './src/emacs' -prune -o -print
理解 find
其实只要把每一个查找的参数看成 find 将要进行求值的``逻辑表达式''就很容
易理解了。同时,作为一个逻辑表达式, -print
总是为真,而 -exec
和
-ok
在他们执行的程序返回非零的时候就为真。例如:
find . \! \( -atime +5 \( -name '*.o' -o -name '*.tmp' \) \) -print
首先看括号里面的 -name '*.o' -o -name '*.tmp'
表示文件名以 .o
或者
.tmp
结尾的文件,记为 exp1
。然后再外一层 -atime +5 exp1
,两个表达式
之间没有指定连接符,因此默认为 -a
,所以表示访问时间大于5天或者满足
exp1
的,记为 exp2
。然后是 \! exp2
,这个就表示不满足 exp2
的,记为
exp3
。最后就是 exp3 -print
了,两者之间采用默认的 -a
连接,即,只有在
exp3
求值为真的时候才对 -print
进行求值(永远为真)。这样就很好理解了。
理解 find 指定的时间
时间是以天为单位指定的,它有下面三种形式:
- 数字。比如
3
表示刚好三天以前的那24个小时的时间区域,或者,换句话说 ,在96个小时以前和72小时以前的那段时间。 - 以减号开头的数字。比如
-3
表示三天以前到现在这个时间段,或者说,72 小时以前到现在这段时间。 - 以加号开头的数字。比如
+3
表示大于3天以前的时间,或者说,比96小时以 前更久远的时间段。
要进行更精确的时间匹配,可以使用 touch 来创建一个指定时间的文件,并使
用 -newer
参数。一个例子:
touch -t 199907031046 /tmp/file1 touch -t 200106042137 /tmp/file2 find . -newer /tmp/file1 \! -newer /tmp/file2 -print
事实上,现在 gnu find 还提供了 -mmin
、 -amin
之类的参数用于更精确的时
间匹配。
小技巧
-exec 参数中文件名替换
在 -exec
中,通常 find 只会替换单独的 {} ,比如 -exec mv {} {}.bak
\;
通常是不会如期望的那样工作,这个时候不得不使用一个脚本。不过, gnu
find 则会不管是否是单独的 {} 都会替换,这样通常会比较方便。
使用自定义的测试
注意 -exec
在程序返回非零的时候才为真,于是,你可以使用自己的测试,例
如:
find . -name '*.[ch]' -exec my_test {} \; -print
通常 -exec
放得越靠后越好,因为每一次测试都会启动一个新的进程,而有多
个条件的时候按照逻辑运算的特性很多时候前面的结果可以直接影响是否有必要
对后面的 -exec
进行求值。