locate
文件查找就是在文件系统上查找查找符合条件的文件。
linux对文件查找的方式有两种:非实时查找和实时查找,非实时查找就是只查找文件系统的索引 ,我们知道系统上所有的文件都是有索引的,我们可以把linux系统的索引理解为就是文件的目录,但是这个目录并不是你建立了文件然后立即更新的,它是有周期性的(定时或者是在系统不繁忙的时候),也就是说你刚才创建的文件,马上使用非实时查找的方式去查找是找不到的,因为它还没有来的及做索引,所以如果我们使用非实时查找的工具都查找刚创建的文件时,要首先把索引更新一下,使用”updatedb”命令即可更新,值得一提的是这个命令并不能随便用,如果你的服务器产生了成千上万的文件,还没来得更新索引,你使用updatedb命令手动更新一下的话,会非常占用资源,如果你服务器在你更新的时候正处于繁忙的状态下,很有可能宕机。
如:
[root@zhanghe ~]# locate zhanghe /home/zhanghe /home/zhanghe/.bash_logout /home/zhanghe/.bash_profile /home/zhanghe/.bashrc /home/zhanghe/.gnome2 /var/spool/mail/zhanghe
FIND当我们使用windows时,当我们打开我的电脑的时候,有的时候会很慢,在搜索框当中会出现进度条,其实这个时候就是在更新索引,那么怎样才能触发系统更新索引呢?windows和linux一样都是周期性的更新(定时、或者不繁忙的时候)。
语法
由于locate的种种弊端,我们经常使用的一般是find命令。
语法:find <在哪里找> <条件>
直接使用find命令什么也不带的话,相当于ls –a 列出所有的文件及目录
查找条件文件名
-name “文件名称”,支持使用通配符,* ? [ ] [^]
-iname “文件名称”,不区分大小写,同样也支持通配符
-regex “正则表达式”,使用此选项可支持正则表达式 应重点掌握
[root@zhanghe ~]# find /home -name *.txt -name /home/zhanghe/zhanghe.txt [root@zhanghe ~]# find /home -iname *.txt -ls -iname 17 1 -rw-r--r-- 1 root root 0 7月 30 03:36 /home/zhanghe/zhanghe.txt [root@zhanghe ~]# find /home -regex ^.*.txt -regex /home/zhanghe/zhanghe.txt [root@nginx ~]# find /etc -regex ".*tion$" /etc/selinux/targeted/active/modules/100/application /etc/selinux/targeted/active/modules/100/motion
属主和属组
-user USERNAME :查找属主为指定用户的文件 -group GROUPNAME :查找属组为指定组的文件 -nouser 查找没有属主的文件 -nogroup查找没有属组的文件
[root@zhanghe ~]# find /home -user zhanghe /home/zhanghe [root@zhanghe ~]# find /home -group zhanghe /home/zhanghe [root@zhanghe ~]# useradd zhangjia;userdel zhangjia #添加一个用户再删除 [root@zhanghe ~]# find /home –nouser -nouser /home/zhangjia /home/zhangjia/.bash_profile [root@zhanghe ~]# find /home -nogroup -nogroup /home/zhangjia /home/zhangjia/.bash_profile
用户ID
如果我们删除了一个用户,那么原本属于这个用户的文件的所有人和所属组就没有了,只剩下id。如果还想要删除的话就得根据uid来查找删除,还是比较实用的。
-
-uid USERID:查找属主为指定UID号的文件
-
-gid GROUPID:查找属组为指定GID号的文件
[root@zhanghe ~]# id zhanghe uid=500(zhanghe) gid=500(zhanghe) 组=500(zhanghe) [root@zhanghe ~]# find /home -uid 500 /home/zhanghe /home/zhanghe/.bash_profile [root@zhanghe ~]# find /home -gid 500 /home/zhanghe /home/zhanghe/.bash_profile
文件类型
-type [l|s|b|p|c|d]
f 普通文件
l 符号链接
d 目录
c 字符设备
b 块设备
s 套接字
[root@zhanghe ~]# find /bin -type l -ls 12058631 0 lrwxrwxrwx 1 root root 4 6月 17 06:00 /bin/egrep -> grep 12058650 0 lrwxrwxrwx 1 root root 3 6月 17 06:00 /bin/gtar -> tar [root@zhanghe ~]# find /dev -type b /dev/sda3 /dev/sda2 /dev/sda1
文件大小
文件大小和时间戳类似,可以使用数轴的方式进行记忆。
时间戳 | 文件大小 | |
---|---|---|
+3 | 四天之前 | 大于3K |
3 | 3天前的一天,3天和4天之间 | 3K----2K之间 |
-3 | 3天以内 | 2K以内 |
[root@zhanghe ~]# find / -size -3k 大于0k小于2K [root@zhanghe ~]# find / -size 3k 大于2k小于等于3K [root@zhanghe ~]# find / -size +3k 大于3K
时间戳
以时间戳记忆的时候一定要结合文件大小进行记忆,两者相关联。
mtime是以天为单位
-mtime n :意义在在n天之前的“一天之内”被更改过过的因为有人 -mtime +n 列出在n天之前(不包含n天)被更改过的文件名 -mtime –n列出在n天之内(包含n天)被更改过的文件。
解析:
-4就代表在四天之内,当然是包括四天的,也就是小于等于四天。
而4就代表在四天之前,五天之内的
而+4就代表在是五天之前了,当然也包括五天,也就是大于等于5天。
权限
权限也有加减号之分,值得一提的是加号在centos7上面不再支持,仅支持负数和整数。
-
+MODE:任何一类(u,g,o)对象的权限中只要能一位匹配即可,有或者之意。
-
-MODE:每一类对象都必须同时拥有为其指定的权限标准,有并且之意。
对于+号的解释:来,来,来,:任何一类(u,g,o)对象的权限中只要能一位匹配即可,有或者之意举个例子:假如一个文件是的权限002的话,那么使用+002可以查找出来,使用+004不可以,因为004的最后一类的权限是4,而4仅仅代表的是读权限罢了,如果是+006就可以,因为+006最后一位是包括读和写,满足一项即可,所以002也满足。
如果文件的权限772,我们使用002也可以匹配到,因为最后一类的最后一位可以被002当中的2匹配到,再次强调,任何一类对象的当中的任意一位被包括即可,但是这个包括是对位的,假如说查看+666的话,满足这个条件的权限就有:200、400、020、222、002、220……442,420,240,444,都可以
[root@zhanghe ~]# find /etc -perm 644 -ls #查找权限是644的文件 5767681 12 -rw-r--r-- 10130 5月 12 2016 /etc/bash_completion.d/yum.bash 5768951 4 -rw-r--r-- 1527 3月 26 2015 /etc/bash_completion.d/scl.bash 5768897 8 -rw-r--r-- 2016 /etc/bash_completion.d/yum-utils.bash [root@zhanghe ~]# find /etc -perm +600 -ls | tail #属主能读**或者**能写即可,0表示忽略 5767999 0 -rw-r--r-- 0 5月 11 2016 /etc/cups/lpoptions 5767996 4 **--w**------- 4064 5月 11 2016 /etc/cups/cupsd.conf 5767994 0 **–r-**------- 0 5月 11 2016 /etc/cups/classes.conf [root@zhanghe ~]# find /etc -perm +222 -ls | tail #任意一类拥有写权限即可 5767999 0 -rw-r--r-- 1 root lp 0 5月 11 2016 /etc/cups/lpoptions 5767996 4 -rw-r----- 1 root lp 4064 5月 11 2016 5767994 0 -rw------- 1 root lp 0 5月 11 2 [root@zhanghe ~]# find /etc/ -perm -644 -ls | tail #权限里面必须包含644,只可多不可少 5768004 0 -rw-r--r-- 1 root lp 0 5月 11 2016 5768000 4 drwxr-xr-x 2 root lp 4096 5月 11 2016 /etc/cups/ppd 5768002 4 -rw-r--r-- 1 root lp 186 5月 11 2016 5767999 0 -rw-r--r-- 1 root lp 0 5月 11 2016 /etc/cups/lpoptions 5767995 0 -rw-r--r-- 1 root lp 0 5月 11 2016 /etc/cups/client.conf 5767998 4 drwxr-xr-x 2 root root 4096 5月 11 2016 #组合条件 -a 与 -o 或 ! 非 [root@local zhanghe]# ls -l -rw-r--r--. 1 root root 0 7月 30 04:09 a.txt #一个普通文件 drwxr-xr-x. 2 root root 1024 7月 30 04:09 b.dir #一个目录 lrwxrwxrwx. 1 root root 13 7月 30 04:09 zhanghe -> /home/zhanghe #一个软链接 [root@local ~]# find /tmp/zhanghe/ -type f -a -iname *.txt #查找普通文件并是txt结尾 /tmp/zhanghe/a.txt [root@local ~]# find /tmp/zhanghe/ -type f -o -type d #查找普通文件或者目录 /tmp/zhanghe/ /tmp/zhanghe/a.txt /tmp/zhanghe/b.dir [root@local ~]# find /tmp/zhanghe/ -type f ! -type l –ls #查找非-=普通文件,非链接文件 15 1 -rw-r--r-- 1 root root 0 7月 30 04:09 /tmp/zhanghe/a.txt
处理动作
-print :默认的处理动作,显示至屏幕
-ls:类似于对查找到的文件执行ls –l命令
-delete:删除查找到的文件
-fls /PATH/TO/SOMFILE查找到的所有文件的长格式信息保存到指定文件中
-ok COMMND {} \; 对查找到的每个文件执行由COMMAND指定的命令
对于每个文件执行命令之前,都会交互要求用户确认
-exec COMMAND {} \; 对查找到的文件执行由COMMAND指定的命令
注意:find传递查找到的文件至后面指定的命令时,查找到所有符合条件的文件一次性传递给后面的命令;有些命令不能授受过多的参数,此时命令执行可能会失败,另一个方式可规避此问题:
find | xargs COMMAND [root@zhanghe ~]# find /tmp -perm +400 –ls [root@zhanghe ~]# find /tmp -perm +400 –delete #操作要小心 [root@zhanghe ~]# find /tmp -perm +400 -exec ls -lh {} \; #注意格式 drw-r--r--. 2 root root 1.0K 7月 30 21:45 a.txt drwx------. 2 root root 1.0K 7月 30 21:46 b.txt [root@zhanghe ~]# find /tmp -perm +400 -ok ls -lh {} \; #注意格式 < ls ... /tmp > ? y #会询问 总用量 4.0K drw-r--r--. 2 root root 1.0K 7月 30 21:45 a.txt drwx------. 2 root root 1.0K 7月 30 21:46 b.txt [root@zhanghe ~]# find /usr -perm +400 -fls /tmp/zhanghe.txt [root@zhanghe ~]# find /usr -perm +400 | xargs+ ls -ldh | tail drwxr-xr-x. 2 0 0 4.0K 9月 23 2011 /usr/src/debug
练习
查找/etc目录下以tions结尾的目录或者文件然后把其详细信息保存到/tmp/下的test.txt文件下
[root@China ~]# find /etc -regex ".*tions$" -fls /tmp/test.txt
查找/etc/下大于5M的文件或目录并显示其详细信息。
[root@China ~]# find /etc -size +5M -exec ls -lh {} \; -rw-r--r--. 1 root root 8.1M 6月 17 06:05 /etc/selinux/targeted/modules/active/policy.kern -rw-r--r--. 1 root root 8.1M 6月 17 06:05 /etc/selinux/targeted/policy/policy.24
查看/etc下小于1M的文件或目录删除之
[root@China ~]# find /etc -size -2 -exec rm –rf {} \; [root@China ~]# find /etc -size -2 –delete #其实可以更简单
查找/var目录下属主为root,且属组为mail的所有文件或目录
find /var –user root –a –group mail
查找/usr目录下不属于root、bin、.或hadoop的所有文件或目录
find /usr –not –user root –a –not –user bin –a –not –user hadoop
查找/etc目录一点点最近一周内容被修改过,同时属主不为root和hadoop的文件或目录
find /etc –mtime -7 –a –not –user root –a –not –user hadoop
查找当前系统没有属主且没有属组,最近一个周内被访问过的文件或目录
find / -nouser –a –nogroup –a –atime -7
查找/etc/目录下大于1M且类型为普通文件的文件或目录
find /etc –size +1M –a –type f
查找/etc目录下所有用户都没有写权限的文件
find /etc/ -not -perm +222 #如不加not为仅满足一个2即可,加上not就是一个2都不能满足。
查找/etc/init.d目录下,所有用户都有执行权限,且其它用户有写权限的文件
find /etc/init.d –perm -113
查看/etc/目录下,修改时间是三天前的文件或目录
find /etc –mtime +3
解析:做上面这个题是纠结的,如果是把三天前理解成为3天之前不包括三天的话使用+3是对的,因为+3意思着大于等于4天;如果把前三天理解成为3天前包括三天的话就得使用+2,因为+2代表大于等于3天。
假如当天是2010年1月5日,我想要查找1月3日创建哪些文件?
[root@China ~]# date 010300002010 2010年 01月 03日 星期日 00:00:00 CST [root@China ~]# touch /tmp/test.txt [root@China ~]# stat /tmp/test.txt|grep "Change" Change: 2010-01-03 00:00:21.000000000 +0800 [root@China ~]# date 010500002010 2010年 01月 05日 星期二 00:00:00 CST [root@China ~]# find /tmp -ctime +2|grep test.txt #没有查找到 [root@China ~]# find /tmp -ctime +1|grep test.txt /tmp/test.txt #成功查找到
解析一下,今天是3号,我创建一个文件test.txt,然后我把时间改为5号。我想要查找到3号创建什么文件,+2表示大于等于3天,也就是三天前,对于当前时间(5号)来说,算上5号这一天的话,大于等于3天指2号那天或者是2号之前创建的文件,所以并没有找到;当我反条件改成+1的话,也就是大于等于2,对于当前的时间(5号)来说,大于等于2天也就是在3号的那天或者是在3天之前,文件正好是3号创建的,所以正好可以查找到。
假如当天是2010年1月5日,我想要查找3天之内创建哪些文件?
[root@China ~]# stat /tmp/test2.txt Change: 2010-01-02 00:00:09.000000000 +0800 [root@China ~]# date 010500002010 2010年 01月 05日 星期二 00:00:00 CST [root@China ~]# find /tmp -ctime -3 /tmp/test.txt #并不能查找到新创建的那个test2.txt文件
解析:-3代表大于大于等于0小于3,也就是说当天或者3,4,5号的任意一天都会被查找到,并不包括2号的那天,为什么?因为是大于等于0小于3,并不是等于3,所以不包括2号。
由此我们总结一下:
如果按照天数查找:
如果让我们查看一下在3天内修改的文件使用-3即可
如果让我们查看一下在3天前修改的文件使用+2即可
如果按照文件大小查找:
大于3M就是+3
小于3M就是-4
如果按照权限查找:
所有都包括某个权限使用减号
仅一项包括使用+号
完全匹配什么号也不加
xargs与exec面试题
今天去同学公司的时候,和他们人事聊了聊,看到了桌子上的面试题,有一道题很有意思,一共有三份试题,来了三个人面试,两个人写错了,其中一个没回答上来,我也是无语了,就这水平,还出来面试,听人事说口气还大的很,不知道从哪里来的自信?不知道他们是昨学的?
面试题是这样:
请找出/test.dir目录下的文件名中包含test关键字的文件并将其全部删除(注:不少于两种方法)
有两位面试者都是这么写的:
find ./ -name "*test*" -type f | rm –rf
这么写看上去是没错的,但实际的操作肯定不行的,还是太嫩了!
为什么这么操作不行呢?find向外输出的是什么?我们是按照文件名查找的,找到的其实就文件名组成的字符流,你把一个字符流通过管道传送给rm命令,rm自然会正常的执行,但是这个字符流与文件路径没有关系,这样删除的只是find的查看后的结果,所以就无法删除,那么要怎么做才行能删除呢?只要将FIND查找到的字符流转换成路径就行了,这样方法就多了,我们可以通过find自带的exec或者借助xargs命令将字符流转换为真实的路径就行了,我们来尝试一下:
[root@localhost ~]# mkdir test.dir ; cd test.dir [root@localhost test.dir]# touch test_{01..06}.txt [root@localhost test.dir]# ls test_01.txt test_02.txt test_03.txt test_04.txt test_05.txt test_06.txt [root@localhost test.dir]# find ./ -name "*test*" -type f | xargs rm -rf [root@localhost test.dir]# ls #空的
再来尝试另一种办法,这种方法是find自带的,效果和上面的例子是一样的。
[root@localhost test.dir]# ls test_01.txt test_02.txt test_03.txt test_04.txt test_05.txt test_06.txt [root@localhost test.dir]# find . -type f -name "*test*" -exec rm -f {} \; [root@localhost test.dir]# ls
再来一种更加简单粗暴的方法:
[root@localhost test.dir]# rm -rf `find ./ -name "*test*" -type f` [root@localhost test.dir]# ls #空的
我们再来举一个例子体会一下:
[root@localhost test.dir]# ls test_01.txt test_02.txt test_03.txt test_04.txt test_05.txt test_06.txt [root@localhost test.dir]# echo testtesttest > test_01.txt [root@localhost test.dir]# echo testtesttest > test_02.txt #除了这两个文件之外都是空的 [root@localhost test.dir]# find -name "*.txt" | rm -rf #我们已经知道,这样肯定是无法删除这些文件的。 [root@localhost test.dir]# ls test_01.txt test_02.txt test_03.txt test_04.txt test_05.txt test_06.txt #果不其然 [root@localhost test.dir]# find -name "*.txt" | grep test #这个操作很正常,将文件名里面包含test的文件都过滤出来了 ./test_01.txt ./test_02.txt ./test_03.txt ./test_04.txt ./test_05.txt ./test_06.txt [root@localhost test.dir]# find -name "*.txt" | xargs grep test ./test_01.txt:testtesttest ./test_02.txt:testtesttest #重要的是这里,加一个xargs,grep就不是在文件名里面找了,而是找文件里面找了!!!
仔细体会一下,体会到了吗?好了,我来总结一下吧!
如果没有xargs的话,grep只会把find的结果当做是字符流,并不是将其当做是文件,当有了xargs之后,这些字符流就变成了真正的路径,其实将xargs换成find自带的exec也是可以的,如下所示:
[root@localhost test.dir]# find -name "*.txt" -exec grep test {} \; #{}就是指前面find的结果,标准输出嘛! testtesttest testtesttest
两个例子
请找出/test.dir目录下的文件名中包含test关键字的文件并将其全部移动到/tmp目录(注:不少于两种方法)
如何操作呢?
第一种方式:
[root@localhost test.dir]# ls test_01.txt test_02.txt test_03.txt test_04.txt test_05.txt test_06.txt [root@localhost test.dir]# mv `find -name "*test*" -type f` /tmp #将命令放置到``当中,自动就能将流转换成有意义的路径
第二种方式:
[root@localhost test.dir]# ls test_01.txt test_02.txt test_03.txt test_04.txt test_05.txt test_06.txt [root@localhost test.dir]# find -name "*test*" -type f -exec mv <----写到这里就写不下去了!
#mv的语法是这样的:mv <被移动的文件> <目标文件夹>,但是这里find会将结果补全到最后也就是<目标文件夹>的位置,怎么办?
#exec是不能用了,我们可以这样,如下所示:
[root@localhost test.dir]# find -name "*test*" -type f | xargs mv -t /tmp
#xargs我们已经理解了,那-t是什么意思?mv -t的意思就是将<被移动的文件>和<目标文件夹>换一下位置,这样find的结果就正好补全到<被移动的文件>,这不就完美了!
第三种方式:
第三种方式与第二种方式差不多,不过我们不用mv的-t选项了,而使用xargs自带的机制了,如下所示:
[root@localhost test.dir]# find -name "*test*" -type f | xargs -i mv {} /tmp;
#这次我们没有改变mv的语法,只是用中括号代替了<被移动的文件>,不要忘了xargs前面要加一个-i的选项,只有这样中括号才有意义!
题目2
请找出/test.dir目录下的文件中包含test关键字的文件并将其全部复制到/tmp目录(注:不少于两种方法)
如何操作呢?
[root@localhost test.dir]# find ./ -name "*test*" -type f | xargs -i cp {} /tmp; [root@localhost test.dir]# find ./ -name "*test*" -type f | xargs cp -t /tmp; [root@localhost test.dir]# cp `find ./ -name "*test*" -type f` /tmp
我打字累了,不解释了,第一个题目看懂后,这一个题目看懂自然不成问题!!!
现在,我真想大声对那三个面试者说:
哈哈!
我们在使用find的时候一定要注意,find的查询范围要界面小一些,如果直接从根直接查找的话容易把内存给打满,一旦内存满了之后就容易触发系统的保护机制,会随机杀死一个占用内存最高的进程,如果系统中运行着mysql,系统很容易会将其干掉!!