免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 1309 | 回复: 0
打印 上一主题 下一主题

find [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2008-07-07 10:27 |只看该作者 |倒序浏览
find
用法:find [path...] [expression]
其中path缺省为./当前目录,expression缺省为-print
根据man页的描述,expression分为三部分:options,tests,actions
options中包括
-daystart(for -amin,-atime,-cmin,-ctime,-mmin,-mtime)从当天开始计算时间,一般和括号中的参数合用,不过具体用途不明,貌似没有-daystart参数也是从命令执行时开始计算的。
-depth从最子层目录开始搜索
-follow排除symbolic links,等价-noleaf,一般在搜索非Linux/Unix的文件系统时使用
-help, --help打印帮助
-maxdepth levels
-mindepth levels
设置搜索目录层级,即仅在不大于/不小于该目录层级进行搜索,如:
$ mkdir -p 0/1/2/3/4/5/6
$ find 0 -maxdepth 3
0
0/1
0/1/2
0/1/2/3
$ find 0 -mindepth 3
0/1/2/3
0/1/2/3/4
0/1/2/3/4/5
0/1/2/3/4/5/6
-mount 限定文件系统,同-xdev
-version, --version打印版本信息
这些参数感觉除了help刚开始接触时有用外其它都不是很常用
tests
其中包括很多内容,也是find最常用和最有用的地方
用的最多的-name pattern
pattern处支持通配符,注意的地方就是一定要养成加""的习惯,虽然很多情况不加也能返回正确的结果,但是有时也会有意想不到的结果,刚开始对此认识不深,举个例子
$ mkdir -p test/test1/test2
$ find -name test*
./test
$ find -name "test*"
./test
./test/test1
./test/test1/test2
这是因为shell在处理命令时首先将通配符扩展,因为当前目录中匹配到了test,所以将test传给了find而不是test*。
继续,如果当前目录中包含一个以上的匹配项的话,find命令将会报错,set -x后看一下结果
$ touch test0
$ set -x
$ find ./ -name test*
+ find ./ -name test test0
find: paths must precede expression
Usage: find [path...] [expression]
继续,-type,Unix或Linux系统中有许多不同的文件类型,可以根据文件类型对文件进行搜索,如
d 目录。
l 符号链接。
s 套接字文件。
b 块设备文件。
c 字符设备文件。
p 命名管道文件。
f 文件
举两个例子:
在当前目录下查找除目录以外的所有类型的文件,可以用:
$ find . ! -type d -print
此处的.和-print可以省略,文章开头说过了,要注意的是!的使用,通配符的"否",当然上面-name选项也可以加!,打印所有非搜索关键字的文件名称,不过什么情况下会用到呢?
第二个例子,虽然用到了后面的内容,不过应该能够理解,查找比test新的文件
$ find -newer test
.
./test0
好了,虽然上面多了个点(当前路径),不过我们能理解,能容忍,但是如果我们想要知道查得结果更详细的情况呢
$ find -newer test -exec ls -l {} \;
-rw-rw-r--  1 wxy wxy     0 Jul  4 11:36 test0
drwxrwxr-x  3 wxy wxy  4096 Jul  4 11:27 test
drwxrwxr-x  3 wxy wxy  4096 Jul  4 11:02 0
drwxrwxr-x  3 wxy wxy  4096 Jul  4 10:59 1
-rw-rw-r--  1 wxy wxy     0 Jul  4 11:36 ./test0
好了,这下你知道那个点的讨厌了?怎么办?
$find -type f -newer test -exec ls -l {} \;
-rw-rw-r--  1 wxy wxy 0 Jul  4 11:36 ./test0
搞定。
文件权限perm mode
按照文件权限模式来查找文件。使用八进制的权限表示法。
如:为了在当前目录下查找文件权限位为755的文件,即文件属主可以读、写、执行,其他用
户可以读、执行的文件,可以用:
find -type f -perm 755
这里注意的是另外两种表达式
perm -mode和perm +mode
man中的解释为
-perm -mode  All of the permission bits mode are set for the file.
-perm +mode  Any of the permission bits mode are set for the file.
一个是所有,一个是任意,很是让人迷糊,有点回到高中英语的感觉,为了更好的说明,我们做个试验
先创建如下文件,为了方便我们仅拿文件属主位进行说明,其余位均置0,当然,别忘了suid和guid位,进行权限查找时很多时候都是针对它们的。
$ ls -l
total 36
---x------  1 wxy wxy  0 Jul  4 14:04 0100
--w-------  1 wxy wxy  0 Jul  4 14:04 0200
--wx------  1 wxy wxy  0 Jul  4 14:05 0300
-r--------  1 wxy wxy  0 Jul  4 14:05 0400
-r-x------  1 wxy wxy  0 Jul  4 14:05 0500
-rw-------  1 wxy wxy  0 Jul  4 14:05 0600
-rwx------  1 wxy wxy  0 Jul  4 13:48 0700
然后依次执行下面的命令并查看结果,这里我没有加-type f
$find -perm -100
$find -perm -200
.
.
.
$find -perm -700
结果应该如下表
$find -perm -100    0100 0300 0500 0700
$find -perm -200    0200 0300 0600 0700
$find -perm -300    0300 0700
$find -perm -400    0400 0500 0600 0700
$find -perm -500    0500 0700
$find -perm -600    0600 0700
$find -perm -700    0700
发现什么了?搜索的权限是个被包含的关系,即如果我搜索1,即可读,那么所有包含可读权限的都会被打印,或者说是至少包含该权限,如果转换成八进制可能会更清楚一些,只转换文件属主:
搜索1,即001        001       001 011 111
搜索2,即010        010       011 110 111
搜索3,即011        011 111
依次类推,至于0,由于任何数都能表示为它本身和0的和,所以搜索0将返回所有的权限值。那么现在我们要检查一下当前目录的所有用户都可读、写、执行的文件,而不考虑用户和组,这可是相当不安全的,怎么办
$find -type f -perm -007
继续,同样的方法,我们进行+mode的试验
$find -perm -100    0100      0300      0500      0700
$find -perm -200         0200 0300           0600 0700
$find -perm -300    0100 0200 0300      0500 0600 0700
$find -perm -400                   0400 0500 0600 0700
$find -perm -500    0100      0300 0400 0500 0600 0700
$find -perm -600         0200 0300 0400 0500 0600 0700
$find -perm -700    0100 0200 0300 0400 0500 0600 0700
这次呢?规律不是很明显了吧,转换成八进制呢?仍然只看文件属主:
$find -perm -100    1(001)     001 011 101 111
$find -perm -200    2(010)     010 011 110 111
$find -perm -300    3(011)     001 010 011 101 110 111
$find -perm -400    4(100)     100 101 110 111
$find -perm -500    5(101)     001 011 100 101 110 111
$find -perm -600    6(110)     010 011 100 101 110 111
$find -perm -700    7(111)     001 010 011 100 101 110 111
现在呢?还没看出来,我们回到刚才的问题吧,all和any的区别
all -号,即所有有1的位置都要匹配,拿011即3读写权限来说的话,就是一定要把两个1的位置匹配了,所以只有011和111
any +号,即任何有1的位置匹配即可,仍然拿011来举例,就是只要有一个1匹配位置即可,所以只有100没有
现在明白了吧,在回过去看一下吧,不过+号不是很常用,至少我几乎没有用过,感兴趣的话了解一下,否则,继续吧
更改时间,这个也是经常用到的
具体的有如下几个:
  -amin n
  查找系统中最后N分钟访问accessed的文件
    -atime n
  查找系统中最后n*24小时访问accessed的文件
    -cmin n
  查找系统中最后N分钟被改变changed文件状态的文件
    -ctime n
  查找系统中最后n*24小时被改变changed文件状态的文件
    -mmin n
  查找系统中最后N分钟被改变文件数据modified的文件
    -mtime n
  查找系统中最后n*24小时被改变文件数据modified的文件
这几个用法相似,记住对应的英文就可以了,accessed很好理解,change和modified的区别在于一个是文件状态一个是文件数据,其中modified过的文件一定是被changed过的,而仅仅改变状态如权限等信息而不改变数据是可以的,平时我们ls -l看到的是modified时间,changed时间可以通过ls -lc来查看,accessed时间可以通过ls -lu来查看,一般来说使用ctime和cmin比较多
除此之外还有三个命令和其类似,即anewer,cnewer和newer,newer相当于mnewer不过没有mnewer这个参数罢了
举两个例子来说明用法:
在系统根目录下查找更改时间在5日以内的文件,可以用:
$ find / -mtime -5 -print 这里的-号表示在...之内
为了在/home/wxy目录下查找访问时间在一小时以前的文件,可以用:
$ find /home/wxy -amin +60 -print       这里的+号表示在...之前,也可以理解在...之外
关于newer,还记得在type那节我们举的例子么?
$find -type f -newer test用以查找比某文件新的文件,当然也可以加上!来查找比某文件旧的文件
两个一起用的话我们就可以抛弃现在这个时间点来查询在某时间段内的文件了,比如现在是下午16:00,而我却因为某种原因想查在今天上午9点到10点的一个重要文件,这么做就可以了
先做两个参照文件
$ touch -t 07040900 czf1
$ touch -t 07041000 czf2
$ ls -l czf?
-rw-rw-r--  1 wxy wxy 0 Jul  4 09:00 czf1
-rw-rw-r--  1 wxy wxy 0 Jul  4 10:00 czf2
然后
$ find . -newer czf1 ! -newer czf2
当然结果可能比我们想要的要多一个,这是因为newer(比它新)的反意!newer的意思是不比它新,当然它本身也不比它新。
大小-size
要说的是大小的单位,一般常用的是有
b 块,默认即是,大小为512字节
c 字节为单位
k 1k字节
再有就是+、-号了,继续举例
为了在当前目录下查找文件长度大于1M字节的文件,可以用:
$ find . -size +1024k -print
为了在当前目录下查找长度不足10块的文件,可以用:
$ find . -size -10 -print
还有一个比较常用的参数时-empty,查找空文件或目录
其余的如-user -nouser -group -nogroup -prune、等等,用法比较简单,另外还有许多,不是经常使用,可以使用man find了解一下
ACTIONS
  这部分的主要掌握-exec和ok命令就可以了
再来回顾一下上面的一条命令
$find -type f -newer test -exec ls -l {} \;
当用find -type f -newer test匹配了一些文件后,对其进行ls -l的操作
关于这个命令的详细解释,我觉得应该是
find -type f -newer test 使用find查找符合条件的文件
-exec find参数,执行命令
ls -l -exec参数的内容,预执行的命令
{} 代替find的结果,感觉有点管道的意思
\ 转义符
;这个都知道吧,两条命令的分割符
-exec也没什么难度,注意格式的正确,不要有多余的空格
-ok和-exec相同,只不过所有的操作都需要进行确认
两个例子:
遍历当前目录中所有文件,输出它们的文件类型,
$ find . -type f -exec file {} \;
曾经有个地方用到了它,给所有未加扩展名的文件分类然后补上扩展名,当时好在只有word、pdf、html等少数格式,因为Linux的file命令好像不能区分word和excel
在/etc目录下搜索所有以passwd开头的文件,查询其中是否包含名为wxy用户
$ find /etc -name "passwd*" -exec grep "wxy" {} \;
xargs
通常使用xargs来代替find自带的exec参数,如上面的两个例子可以改写成
$ find . -type f |xargs file
$ find /etc -name "passwd*" |xargs grep "wxy"
    至于为什么使用xargs来代替-exec,一般的解释是在使用find命令的-exec选项处理匹配到的文件时,find命令将所有匹配到的文件一起传递给exec执行。而有些系统对能够传递给exec的命令长度有限制,这样在find命令运行几分钟之后,就会出现溢出错误。错误信息通常是“参数列太长”或“参数列溢出”。而find命令把匹配到的文件传递给xargs命令,而xargs命令每次只获取一部分文件而不是全部,不像-exec选项那样。这样它可以先处理,最先获取的一部分文件,然后是下一批,并如此继续下去。而在有些系统中,使用-exec选项会为处理每一个匹配到的文件而发起一个相应的进程,并非将匹配到的文件全部作为参数一次执行;这样在有些情况下就会出现进程过多,系统性能下降的问题,因而效率不高;而使用xargs命令则只有一个进程。另外,在使用xargs命令时,究竟是一次获取所有的参数,还是分批取得参数,以及每一次获取参数的数目都会根据该命令的选项及系统内核中相应的可调参数来确定。
    而我在进行find / -type f -exec file {} \;命令的时候却没有发现类似错误,可能是我的例子不恰当或者系统(RHAS4)恰好不在其描述的有些系统之内吧,不过按照上面所描述,如果使用exec执行是将find匹配到的文件一起传递给exec执行的话,那么就会有个先后顺序,即先find再exec的命令;而find|xargs的话就没有这个问题了,find一批xargs一批,速度上应该是xargs要快于exec的方式的。
最后引用man页中的OPERATORS部分结尾
! expr:True if expr is false.
-not expr:Same as ! expr.
expr1 expr2:And (implied); expr2 is not evaluated if expr1 is false.
expr1 -a expr2:Same as expr1 expr2.
expr1 -and expr2:Same as expr1 expr2.
expr1 -o expr2:Or; expr2 is not evaluated if expr1 is true.
expr1 -or expr2:Same as expr1 -o expr2.
expr1 , expr2:List;  both expr1 and expr2 are always evaluated.  The value of expr1 is discarded; the value of the list is the value of expr2.


本文来自ChinaUnix博客,如果查看原文请点:http://blog.chinaunix.net/u2/72669/showart_1074694.html
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP