find命令详解
find
find命令表示在目录层级中查找文件
格式
find [OPTIONS] [查找起始路径] [查找条件] [处理动作]
查找起始路径:指定具体搜索目标其实路径;默认为当前目录
查找条件:指定的查找标准,可以根据文件名、大小、类型、从属关系、权限等标准进行。
默认为找出指定路径下的所有文件
处理动作:对符合查找条件的文件做出操作,例如删除等操作;默认为输出至标准输出
查找条件
根据文件名查找:
\-name PATTERN:仅仅通过文件名查找,这里支持的PATTERN指的是文件名globbing
\-iname PATTERN:忽略大小写查询
\-regex pattern:基于正则表达式模式查找文件,匹配整个路径,而不是basename,匹配整个路径表示pattern是整个路径,而不是路径中的某个片段字符串
[root@localhost ~]# find /etc/ -name *tab #查找/etc/目录下文件名(basename)以tab结尾的所有文件
根据文件从属关系查找:
\-user USERNAME:根据文件属主查找文件
\-group GRPNAME:根据文件的属组查找文件
\-uid ####:根据文件的UID查找文件
在一个用户被删除之后,这个用户的文件的属主就会变成UID号而不是USERNAME了
\-gid ####:查找属组指定的GID所有文件
\-nouser:查找没有属主的文件
\-nogroup:查找没有属组的文件
#添加一个shirley用户,并在shirley用户的家目录创造一个文件
[root@localhost ~]# useradd shirley
[root@localhost ~]# su - shirley
[shirley@localhost ~]$ touch shirley.file
[shirley@localhost ~]$ exit
logout
#删除shirley用户,发现shirley用户的文件的属主和属组变成了uid。
[root@localhost ~]# userdel shirley
[root@localhost ~]# ls -l /home/shirley/shirley.file
-rw-rw-r-- 1 503 504 0 Dec 16 13:21 /home/shirley/shirley.file
#再这样的情况下,如果添加用户他的uid恰巧就是503,那么这个文件就会属于他,这是不安全的
#按照uid查找文件
[root@localhost ~]# find /home/ -uid 503
/home/shirley
#按照nouser查找文件
[root@localhost ~]# find /home/ -nouser
/home/shirley
/home/shirley/.bash_profile
根据文件类型查找:
\-type TYPE:
f:普通文件
d:目录文件
l:符号连接文件
b:块设备文件
c:字符设备文件
p:管道文件
s:套接字文件
根据文件大小查找:
\-size [+|-]#UNIT
常用单位:k,M,G 用三个区间表示了所有的文件大小
如果没有使用+-则查找的大小是一个开区间(#-1,#]
如果使用+-则-表示[0,#-1];+表示(#,oo)
文件的大小174.2k通过ls会变为175k
[root@localhost ~]# ls -lh functions
-rw-r--r-- 1 root root 5.1K Dec 16 13:35 functions
[root@localhost ~]# ls -l functions
-rw-r--r-- 1 root root 5201 Dec 16 13:35 functions
#根据大小查找
[root@localhost ~]# find ./ -size 5.2k
find: Invalid argument `5.2k' to -size
[root@localhost ~]# find ./ -size 6k
./functions
#上面的结果说明了是一个开区间
根据时间戳查找:
以“天”为单位
-atime [+|-] #
-atime + 3
#:等于#天,[#,#+1)
表示前#天到前#+1天之间的那个时间
-#:少于#天,[0,#)
+#:超过#天,[#+1,oo)
-mtime
-ctime
以“分钟”为单位
-amin
-mmin
-cmin
根据权限查找:
\-perm mode
精确权限匹配,匹配所有权限,即ugo都匹配
\-perm -mode
每一类用户ugo的权限中的每一位都符合条件,但是不是精确匹配
9位中只要提供的都要满足,此处是与关系
\-perm /mode
任何一类用户ugo的权限中的任何一位符合条件,注意是一位不是一组
9位权限只要有个一符合就为真,此处是或关系
注意:-mode和/mode中权限为0表示不关心,而在mode中就表示权限位为0!
[root@localhost ~]# mkdir perm
[root@localhost ~]# cd perm
[root@localhost perm]# touch perm.root
#精确权限匹配,提供了权限位就一定要匹配,一下表示匹配全限制644
[root@localhost perm]# find ./ -perm 644 -ls
1048609 0 -rw-r--r-- 1 root root 0 Dec 16 13:48 ./perm.root
#以下表示精确匹配600权限的文件,没有查询到
[root@localhost perm]# find ./ -perm 600
#以下表示ugo中这三个权限位中,只要提供了权限位,就一定要满足,如果没有提供就不管,600匹配了u的权限
[root@localhost perm]# find ./ -perm -600 -ls
1048605 4 drwxr-xr-x 2 root root 4096 Dec 16 13:48 ./
1048609 0 -rw-r--r-- 1 root root 0 Dec 16 13:48 ./perm.root
#下面的查找也找到了,再一次说明了这个-mode不是精确查找,u位为4并不是说他只能为4而是说u要有4权限,因为6包含权限4,所以匹配到了;如果改成410,那么就不能匹配了,因为想与结果为假。
[root@localhost perm]# find ./ -perm -400 -ls
1048605 4 drwxr-xr-x 2 root root 4096 Dec 16 13:48 ./
1048609 0 -rw-r--r-- 1 root root 0 Dec 16 13:48 ./perm.root
[root@localhost perm]# find ./ -perm -410 -ls
1048605 4 drwxr-xr-x 2 root root 4096 Dec 16 13:48 ./
#可以发现u有一位匹配,go一位都不匹配,但是结果为真,说明ugo其中只要有一位满足就行了
[root@localhost perm]# find ./ -perm /211 -ls
1048605 4 drwxr-xr-x 2 root root 4096 Dec 16 13:48 ./
1048609 0 -rw-r--r-- 1 root root 0 Dec 16 13:48 ./perm.root
组合测试:
\-a:表示逻辑与;默认就是-a
\-o:表示逻辑或
\-not,!:表示逻辑非
处理动作
\-print:输出至标准输出,默认动作
\-ls:类似于对查找到的文件执行ls -l命令,输出文件的详细信息
\-delete:删除查找到的文件
\-fls /PATH/TO/SOMEFILE:把查找到的结果的详细信息保存放到指定文件中
\-ok COMMAND {} \; :表示对查找到的每个文件执行由此处COMMAND表示的命令
这个命令中一个符号都不可以改变,{}表示find到的文件列表,\;是固定格式,每次COMMAND都会提示用户确认
\-exec COMMAND {} \; :表示对查找到的文件执行由COMMAND指定的命令,但是不再提示用户进行确认
-exec mv {} {}.danger \; 这就是在文件名后面添加danger后缀
[root@localhost ~]# tree
.
├── anaconda-ks.cfg
├── functions
├── install.log
└── install.log.syslog
#找到functions文件并更名为functions.mv
[root@localhost ~]# find -name functions -exec mv {} {}.mv \;
[root@localhost ~]# tree
.
├── anaconda-ks.cfg
├── another
│ └── functions.mv
├── functions.mv
├── install.log
└── install.log.syslog
注意:find传递查找的文件路径之后面的命令时,实现查找出所有符合条件的文件路径,并一次性传递给后面的命令
但是,有些命令不能接受过长的参数,此时命令执行会失败;另一种方式可以规避这种问题
解决方法是:
find | xargs COMMAND
例子
1、找出/tmp目录下属主为非root的所有文件
~]# find /tmp ! -user root
2、找出/tmp目录下文件名中不包含fstab字符串的文件
~]# find /tmp ! -iname *fstab*
3、找出/tmp目录下属主为非root,而且文件名不包含fstab字符串的文件。
~]# find /tmp ! -name *fstab* -a ! -user root
~]# find /tmp ! \( -name *fstab* -o -user root \)
组合条件中括号要转义,而且括号和条件之间用空格隔开
4、查找/var目录下属主为root,且属组为mail的所有文件或目录
~]# find /var -user root -group mail
~]# find /var -user root -a -group mail
组合条件之间如果没有逻辑运算,那么默认就是与运算
5、查找/usr目录下不属于root,tom或jerry的所有文件或目录;用两种方法
~]# find /usr ! -user tom -o ! -user jerry -o ! -user root
~]# find /usr ! \( -user tom -a -user jerry -a -user root \)
--上面这两个命令其实是错的--
因为或运算最终的结果是把所有满足各个条件的文件都找出来,上面的两个命令会找出当前目录下的所有文件(包括隐藏文件)
以下是上述命令的结果截图:
正确的命令应该是,它把不是上述三个属主的文件都找了出来
[root@localhost ~]# find /tmp ! -user root -a ! -user tom -a ! -user jerry
/tmp/husa.file
6、查找/etc目录下最近一周内起内容修改过,且属主不是root用户也不是hadoop用户的文件或目录;
~]# find /etc -mtime -7 ! \( -user root -o -user hadoop\)
这里为什么是-7呢,因为-7表示[0,24*7)小时之内的时间,如果-mtime 7就表示[7*24,8*24)之间的时间了
7、查找当前系统上没有属主属组,且最近一周内曾被访问过的文件或目录
~]# find / -nouser -nogroup -atime -7
8、查找/etc目录下大于1M且类型为普通文件的所有文件
~]# find /etc -size +1M -type f -exec ls -lh {} \;
注意,如果这里是小于1M的文件,就应该是,因为-2表示[0,2-1],这里还会包括1M大小的文件
~]# find /etc -size -2M -type f -exec ls -lh {} \;
9、查找/etc目录下所有用户都没有写权限的文件
~]# find /etc ! -perm /222 -ls
/perm 222表示至少有一个用户有写权限
10、查找/etc目录至少有一类用户没有执行权限的文件
~]# find /etc -not -perm -111 -ls
至少一类用户没有执行权限的反面是所有用户都有执行权限,那么就是-perm 111
11、查找/etc/init.d/目录下,所有用户都有执行权限,且其他用户有写权限的所有文件
~]# find /etc/init.d -perm -113 -type f -ls
所有用户有执行权限-perm 111 其他用户有写权限-perm 002,二者与就是-perm 123
locate
在文件系统上查找符合条件的文件;
实现工具:locate,find
locate:
依赖于事先构建好的索引库
系统自动实现:系统有计划任务,一般每天更新数据库
手动更新数据库:updatedb
特性:
查找速度快
非实时查找
模糊查找
locate [OPTION]... PATTERN...
-r:支持基本正则表达式
-b:只匹配basename相同的路径,其他的不匹配
-c:统计出共有多少个符合条件的文件
updatedb命令是一个消耗资源的命令,它要遍历整个根文件系统
xargs
xargs - build and execute command lines from standard input
从标准输入中建立和执行命令
xargs从标准输入读取项目,并把空白符号、新行作为分隔符,它会多次执行来自标准输入的命令,不管他们初始的参数有多长,标准输入中的空白行会被忽略
因为Unix的文件名可以包含空格和换行,因此也会带来很大的麻烦。xargs就不能正确的处理这种问题。在这种情况下,最好使用-0选项,他会避免这种问题
\-print0选项是用来消除传递的输入中以空字符null character作为分隔符
常用选项:
-a file
以文件作为输入,而不是标准输入
[root@localhost ~]# cat hello.c
#include <stdlib.h>
int main(){
int ival = 100;
printf("%d\n",ival);
printf("hello world");
return 0;
}
[root@localhost ~]# xargs -a hello.c echo
#include <stdlib.h> int main(){ int ival = 100; printf(%d\n,ival); printf(hello world); return 0; }
以上可以看出xargs默认是以回车作为分隔符。传递给命令的参数之间的分隔符是空格
--null
-0
使用-0选项,标准输入会把特殊的字符当作普通的自负,并且以空字符作为结束标志,这个选项对于命令中包含空格、引号、反斜线
GNU的find命令的-print-选项会为这个选项产生适合的输入
-d delim
自己定制xargs的分隔符
[root@localhost ~]# xargs -a hello.c -d " " echo
#include <stdlib.h>
int main(){
int ival = 100;
printf("%d\n",ival);
printf("hello world");
return 0;
}
可以看到定制分隔符为空格,那么遇到一个空格就把这个参数传递给了echo命令,但是参数之间又是用空格分割的,所以echo就按照原样把c文件打印下来了
-E eof-str
指定输入的结束符
[root@localhost ~]# xargs -a hello.c -E int echo
#include <stdlib.h>
可以发现echo命令以int为结束标志。注意这里的结束标志不要是用引号引起来,除非真的以引号作为结束标志
-n max-args
指定xargs传递的最大参数个数,默认是传递所有的