linux包之findutils之find和xargs命令

时间:2022-02-04 01:57:11

解释

[root@localhost ~]# rpm -qa|grep find
findutils-4.4.2-6.el6.x86_64

find 路径 测试 动作 三个步骤的处理过程
查找一个或多个目录树,根据指定的测试条件,查找符合特定标准的文件,执行指定的动作
三种路径 find /bin . ~
find path -options [ -print ] [ -exec -ok command ] {} \; 占位符机制,这种机制中的占位符是“{}”。

样例
缺省情况下,find会从指定的目录搜索,并递归的搜索其子目录。
按文件名
查找以大写字母开头的文件
[root@localhost script]# find ~ -name "[A-Z]*"
在当前目录下查找以f开始的文件,并把结果输出到dddddd中
[root@localhost script]# find . -name "f*" -fprint dddddd
查找以f或以c开头的文件
[root@localhost script]# find . -name "f*" -o -name "c*"
[root@coreserv log]# find . -name "*.log"|xargs ls -l
[root@coreserv log]# find . -name "d*"|xargs ls -l
按权限
[root@CentOS5 /]# find /var -perm 600|xargs ls -l
[root@CentOS5 /]# find /etc -perm -600|wc -l
2156
[root@CentOS5 /]# find /etc -perm +600|wc -l
2162
[root@CentOS5 /]# find /etc/sysconfig -perm +600|wc -l
117
[root@CentOS5 /]# find /etc/sysconfig -perm -600|wc -l
117
[root@CentOS5 /]# find /etc/sysconfig -perm 600|wc -l
3
按类型
查找包含if行的所有文件
[root@localhost script]# find . -type f |xargs grep "if"
[root@CentOS5 /]# find /etc -type l|xargs ls -l
-type:后面指定文件的类型。
b - 块设备文件。
d - 目录。
c - 字符设备文件。
p - 管道文件。
l - 符号链接文件。
f - 普通文件。
按大小
-size [+/-]100[c/k/M/G]: 表示文件的长度为等于[大于/小于]100块[字节/k/M/G]的文件。
-empty: 查找空文件。
[root@CentOS5 /]# find /var -empty -type f|xargs ls -l
[root@CentOS5 /]# find /var -size +5M -type f|xargs ls -l
按按更改时间比指定文件新或比文件旧的方式查找
[root@CentOS5 file_user]# ls -ltr
[root@CentOS5 file_user]# ll
total 80
-rw------- 1 root root 61762 May 22 15:36 messages
-rw-r--r-- 1 root root 12 May 22 15:39 pam_smb.conf
-rw-r--r-- 1 root root 1927 May 22 15:38 passwd
-rw-r--r-- 1 root root 490 May 22 15:37 yum-updatesd.conf
[root@CentOS5 /]# find . ! -newer passwd |xargs ls -l passwd以前的
[root@CentOS5 /]# find . -newer passwd passwd以后的
按文件时间属性查找:
-atime -n[+n]: 找出文件访问时间在n日之内[之外]的文件。
-ctime -n[+n]: 找出文件更改时间在n日之内[之外]的文件。
-mtime -n[+n]: 找出修改数据时间在n日之内[之外]的文件。
-amin -n[+n]: 找出文件访问时间在n分钟之内[之外]的文件。
-cmin -n[+n]: 找出文件更改时间在n分钟之内[之外]的文件。
-mmin -n[+n]: 找出修改数据时间在n分钟之内[之外]的文件。
[root@coreserv log]# find . -cmin -3|xargs ls -l
[root@coreserv log]# find /var/log -ctime -2 |xargs ls -l
[root@coreserv log]# find /var/log -maxdepth 1 -ctime -2 |xargs ls -l

[root@225-oth logs]# find . -ctime +2|xargs ls -l  2天之前的

[root@225-oth logs]# find . -cmin +120|xargs ls -l  2小时之前的

[root@225-oth log]# find . -name "*.log" -mtime -2|xargs ls -l
[root@225-oth log]# find . -name "*[0-9]" -size +300k |xargs ls -l
[root@225-oth log]# find . -name "*[0-9]" -size -300k -ctime -1|xargs ls -l

find /var/tmp/stuff -mtime +90 -delete
[root@250-shiyan ~]# find /var/log/ -name "*[0-9]"  -ctime -2 -ls

####查找大批量的文件时最合适了
[root@rac02 u01]# find /u01 -size +10M -type f|grep log_[0-9][0-9].xml
[root@rac02 u01]# find /u01 -size +10M -type f|grep l[0-9][0-9]

[root@8a2serv com1_bak]# crontab -l
*/60  *  *  *  * /usr/sbin/ntpdate 192.168.2.1 && /sbin/clock -w > /dev/null 2>&1
0 */1 * * * sh /etc/asterisk/logger.sh
10 12 */1 * * find /u01/asterisk/messages-201* -ctime +3 | xargs rm -f

按目录层次,默认递归
-maxdepth 1 当前目录,然后依次类推
按属主属组查找
-user prtg
排除指定子目录查找
-path pathname -prune: 避开指定子目录pathname查找。
-path expression -prune: 避开表达中指定的一组pathname查找。
需要说明的是,如果同时使用-depth选项,那么-prune将被find命令忽略。
find . -path "./DontSearchPath" -prune -o -name "datafile*"
find . \( -path "./DontSearchPath" -o -path "./DoSearchPath" \) -prune -o -name "datafile*"
-fstype 查找位于某一类型文件系统中的文件,这些文件系统类型通常可以在配置文件/etc/fstab中找到
-mount 在查找文件时不跨越文件系统mount点
-follow 如果find命令遇到符号链接文件,就跟踪至链接所指向的文件
-cpio 对匹配的文件使用cpio命令,将这些文件备份到磁带设备中。
查找大于10M并列出详细信息
#-size n[c]查找文档长度为n块的文档 有[c]表示文档长度以字节计算
#-exec command {} \; 将查到的文档执行command操作,{} 和 \;之间有空格
#-ok 和-exec相同,只是在操作前要询用户
[root@localhost script]# find ~ -size +10000000c |xargs ls -l
[root@localhost script]# find ~ -size +10000000c -exec ls -l {} \;
[root@localhost script]# find ~ -size +10000000c -ok ls -l {} \;
基于找到的文件执行指定的操作:
-exec: 对匹配的文件执行该参数所给出的shell命令。相应命令的形式为'command' {} \;,注意{}和\;之间的空格,同时两个{}之间没有空格
-ok: 其主要功能和语法格式与-exec完全相同,唯一的差别是在于该选项更加安全,因为它会在每次执行shell命令之前均予以提示,只有在回答为y的时候, 其后的shell命令才会被继续执行。需要说明的是,该选项不适用于自动化脚本,因为该提供可能会挂起整个自动化流程。
#找出距此时2天之内创建的文件,同时基于find的结果,应用-exec之后的命令,即ls -l,从而可以直接显示出find找到文件的明显列表。
/> find . -ctime -2 -exec ls -l {} \;
-rw-r--r--. 1 root root 279 Nov 11 08:45 ./users2
-rw-r--r--. 1 root root 48217 Nov 12 00:57 ./install.log
-rw-r--r--. 1 root root 37 Nov 12 00:56 ./testfile.dat
-rw-r--r--. 1 root root 183 Nov 11 08:02 ./users
-rw-r--r--. 1 root root 10530 Nov 11 23:08 ./test.tar.bz2
#找到文件名为*.log, 同时文件数据修改时间距此时为1天之内的文件。如果找到就删除他们。有的时候,这样的写法由于是在找到之后立刻删除,因此存在一定误删除的危险。
/> ls
install.log testfile.dat test.tar.bz2 users users2
/> find . -name "*.log" -mtime -1 -exec rm -f {} \;
/> ls
testfile.dat test.tar.bz2 users users2
在控制台下,为了使上面的命令更加安全,我们可以使用-ok替换-exec,见如下示例:
/> find . -name "*.dat" -mtime -1 -ok rm -f {} \;
< rm ... ./testfile.dat > ? y #对于该提示,如果回答y,找到的*.dat文件将被删除,这一点从下面的ls命令的结果可以看出。
/> ls
test.tar.bz2 users users2

xargs
在使用find命令的-exec选项处理匹配到的文件时,find命令将所有匹配到的文件一起传递给exec执行。不幸的是,有些系统对能够传递给exec的命令长度有限制,这样在find命令运行几分钟之后,就会出现溢出错误。错误信息通常是“参数列太长”或“参数列溢出”。这就是xargs命令的用处所在,特别是与find命令一起使用。Find命令把匹配到的文件传递给xargs命令,而xargs命令每次只获取一部分文件而不是全部,不像-exec选项那样。这样它可以先处理最先获取的一部分文件,然后是下一批,并如此继续下去。
在有些系统中,使用-exec选项会为处理每一个匹配到的文件而发起一个相应的进程,并非将匹配到的文件全部作为参数一次执行;这样在有些情况下就会出现进程过多,系统性能下降的问题,因而效率不高;而使用xargs命令则只有一个进程。另外,在使用xargs命令时,究竟是一次获取所有的参数,还是分批取得参数,以及每一次获取参数的数目都会根据该命令的选项及系统内核中相应的可调参数来确定。
1、多行变成单行
-bash-3.2# cat test.txt
a b c d e f
g o p q
-bash-3.2# cat test.txt |xargs
a b c d e f g o p q
2、单行变成多行
-bash-3.2# cat test.txt
a b c d e f g o p q
-bash-3.2# cat test.txt |xargs -n 2
a b
c d
e f
g o
p q
3、删除某个重复的字符来做定界符
-bash-3.2# cat test.txt
aaaagttttgyyyygcccc
-bash-3.2# cat test.txt |xargs -d g
aaaa tttt yyyy cccc
4、删除某个重复的字符来做定界符后,变成多行
-bash-3.2# cat test.txt |xargs -d g -n 2
aaaa tttt
yyyy cccc
5、用find找出文件以txt后缀,并使用xargs将这些文件删除
-bash-3.2# find /root/ -name "*.txt" -print0 |xargs -0 rm -rf #查找并删除
-bash-3.2# find /root/ -name "*.txt" -print #再次查找没有
6、查找普通文件中包括thxy这个单词的
-bash-3.2# find /root/ -type f -print |xargs grep "thxy"
/root/1.doc:thxy
7、查找权限为644的文件,并使用xargs给所有加上x权限
-bash-3.2# find /root/ -perm 644 -print|xargs chmod a+x
-bash-3.2# find /root/ -perm 755 -print

想查找当前文件夹及子文件夹里的同时含有b字符和3字符的文件:用到正则表达式技术
# find . -regex ‘.*b.*3′
-regex:表示使用正则表达式进行匹配。请注意,此命令会和“全路径”进行匹配,也就是说前面要加.*,因为输出结果中会有“./”符号。

只在本级目录,不递归
[root@250-shiyan ~]# find ./ -maxdepth 1 -type f -perm 744
./chpa1.sh
./jjj

排除frag目录
[root@250-shiyan ~]# find -path './sh/frag*' -prune -o -type f -perm 744
./sh/awk/strip.awk
./sh/prog/menu2
./sh/prog/menu
./sh/frag
./sh/sed/game2
./sh/sed/game3
./sh/sed/game
./sh/grep/a.grep
./sh/grep/te.sh
./chpa1.sh
./jjj

而我之前一直都是用的双引号,也没有遇到问题,这次却报错了
ssh $ip "cd $path;find . -name 'access.$month*.log' -print -exec zip -r access.$month.zip {} \;"
将"access.$month*.log"修改成单引号后,木有再见报错

在Windows中可以在某些路径中查找文件,也可以设定不在某些路径中查找文件,下面用Linux中的find的命令结合其-path -prune参数来看看在Linux中怎么实现此功能。

假如在当前目录下查找文件,且当前目录下有很多文件及目录(多层目录),包括dir0、dir1和dir2 ...等目录及dir00、dir01...dir10、dir11...等子目录。

. 在当前目录下查找所有txt后缀文件

    find ./ -name *.txt

.在当前目录下的dir0目录及子目录下查找txt后缀文件

    find ./ -path './dir0*' -name *.txt

.在当前目录下的dir0目录下的子目录dir00及其子目录下查找txt后缀文件

    find ./ -path '*dir00*' -name *.txt

.在除dir0及子目录以外的目录下查找txt后缀文件

    find ./ -path './dir0*' -a -prune -o -name *.txt -print

说明:-a 应该是and的缩写,意思是逻辑运算符‘或’(&&); -o应该是or的缩写,意思是逻辑运算符‘与’(||), -not 表示非.

命令行的意思是:如果目录dir0存在(即-a左边为真),则求-prune的值,-prune 返回真,‘与’逻辑表达式为真(即-path './dir0*' -a -prune 为真),find命令将在除这个目录以外的目录下查找txt后缀文件并打印出来;如果目录dir0不存在(即-a左边为假),则不求值-prune ,‘与’逻辑表达式为假,则在当前目录下查找所有txt后缀文件。

.在除dir0、dir1及子目录以外的目录下查找txt后缀文件

    find ./ \( -path './dir0*' -o -path './dir1*' \) -a -prune -o -name *.txt -print

注意:圆括号()表示表达式的结合。即指示 shell 不对后面的字符作特殊解释,而留给 find 命令去解释其意义。由于命令行不能直接使用圆括号,所以需要用反斜杠'\'进行转意(即'\'转意字符使命令行认识圆括号)。同时注意'\(','\)'两边都需空格。

.在dir0、dir1及子目录下查找txt后缀文件

    find ./ \( -path './dir0*' -o -path './dir1*' \) -a -name *.txt -print

+. 在所有以名为dir_general的目录下查找txt后缀文件

find ./ -path '*/dir_general/*' -name *.txt -print