find命令-exec选项,find命令配合xargs
一、find命令-exec选项(xargs不是find的选项)
-exec command {} \;
1、正则匹配查找(/etc/目录下搜索以s为文件名开头的文件;)
find /etc/ -type f -name "s*"
注意:如果文件名使用正则匹配,那么需要加双引号,否则会报错;这里只列举了通配匹配方式,其他正则方式如"[ab].sh",“s?”等不再介绍;
2、统计当前目录中以.html结尾的文件总大
方法1: find . -name "*.html" -exec du -k {} \; |awk '{sum+=$1}END{print sum}' 方法2: for size in $(ls -l *.html |awk '{print $5}'); do sum=$(($sum+$size)) done echo $sum
3、使用-exec选项(shell命令执行)
在当前目录下搜索以1为文件名开头的文件,并复制到/root目录下; find ./ -type f -name "1*" -exec cp {} /root \; 查找当前目录下所有以txt文件中包含123的数字都替换成5678 find ./ -name "*.txt" -exec grep "123" {} \; -exec sed -i 's/123/5678/g' {} \;
注:选项-exec,后面跟要执行的shell命令,{} 花括号代表前面find查找出来的文件名,即把搜索的文件名放到花括号中,注意反斜杠\和分号;之间没有空格,这种用法通常是把搜索的结果做处理;
4、统计根目录下面所有的 jpg 的文件的大小
find / -name *.jpg -exec wc -c {} \;|awk '{print $1}'|awk '{a+=$1}END{print a}'
二、find命令配合xargs
find ./ -type f -name "1*" | xargs -i cp {} /tmp #在当前目录下搜索以1为文件名开头的文件,并复制到/tmp目录下; find $DEL_DIR -mindepth 1 -type d -mtime +365 | xargs rm -rf
注:
xargs不但可以和find配合使用,配合其他指令也是可以的,比如配合awk
docker ps | grep grafana | awk -F" " '{ print $NR }' | xargs docker stop
三、exec和xargs二者的区别
1.使用-exec选项,此选项是把参数一个一个传递给shell命令,即传递一个文件名执行一次cp命令;
2.而xargs命令,是把参数一次性传递,即把搜索的所有文件名一次姓传给shell命令处理;
四、find查找重复文件并删除
1、查找
示例:cronjob.tar是重复文件,存在于哪个路径下
$ find -not -empty -type f -printf "%s\n" | sort -rn |uniq -d | xargs -I{} -n1 find -type f -size {}c -print0 | xargs -0 md5sum | sort | uniq -w32 --all-repeated=separate | cut -b 36- /cronjob.tar /zjz/cronjob.tar /zjz/test/cronjob.tar /linux-4.19.163.tar.xz /zjz/linux-4.19.163.tar.xz /test.txt /zjz/test.txt
用法:复制命令在当下想要查询的路径的执行,会对当前文件夹及子文件夹内的所有文件进行查重显示。
拆解:
第一句
find -not -empty -type f -printf "%s\n"
-not -empty是要寻找非空文件;-type f是指寻找常规文件;-printf “%sn”:它实际表示的是文件的大小,单位为bytes(man find),n是换行符。所以这句话的意思是输出所有非空文件的大小。
第二句
sort -rn
sort是排序,-n是指按大小排序,-r是指从大到小排序(逆序reverse)
第三句:
uniq -d
uniq是把重复的只输出一次,而-d指只输出重复的部分(如9出现了5次,那么就输出1个9,只出现了1次,并非重复出现的数字,不输出)
第四句:
xargs -I{} -n1 find -type f -size {}c -print0
这一部分分两部分看,第一部分是xargs -I{} -n1,xargs命令将之前的结果转化为参数,供后面的find调用,其中-I{}是指把参数写成{},而-n1是指将之前的结果一个一个输入给下一个命令(-n8就是8个8个输入给下一句,不写-n就是把之前的结果一股脑的给下一句)。后半部分是find -type f -size {}c -print0,find指令我们前面见过,-size{}是指找出大小为{}bytes的文件,而-print0则是为了防止文件名里带空格而写的参数。
第五句:
xargs -0 md5sum
xargs我们之前说过,是将前面的结果转化为输入,那么这个-0又是什么意思?man一下xargs,我们看到-0表示读取参数的时候以null为分隔符读取,这也不难理解,毕竟null的二进制表示就是00。后面的md5sum是指计算输入的md5值。
第六句:sort是排序
第七句:
uniq -w32 --all-repeated=separate
uniq -w32是指寻找前32个字符相同的行,原因在于md5值一定是32位的,而后面的--all-repeated=separate是指将重复的部分放在一类,分类输出。
第八句:
cut -b 36-
由于结果带着md5值,不是很好看,所以我们截取md5值后面的部分,cut是文本处理函数,这里-b 36-是指只要每行36个字符之后的部分。
在Linux下很好看,实际上把输出文件放到Windows上,就会发现换行全没了,这是由于Linux下的换行是\n,而windows要求\nr,为了解决这个问题,我们最后执行一条指令,将\n转换为\nr:
cat result.txt | cut -c 36- | tr -s 'n'
2、find ... -delete 删除操作(危险,慎重)
$ ls cronjob.tar linux-4.19.163.tar.xz test.txt zjz $ find ./ -type f -empty ##错误 $ find ./ -type f -not -empty ##正解 ./linux-4.19.163.tar.xz ./cronjob.tar ./test.txt ./zjz/cronjob.tar ./zjz/linux-4.19.163.tar.xz ./zjz/test.txt ./zjz/test/cronjob.tar $ find ./ -type f -not -empty -delete $ ls -R zjz/ zjz/: test
五、常用的按要求查找
语法
find path -option [ -print ] [ -exec -ok command ] {} \;
1、按时间查找(-atime访问时间 -mtime文件内容修改时间 -ctime文件自身属性修改时间)
find /tmp -type f -mtime +7 -name "*.sh" | xargs -i cp {} /data find /tmp -type f -mtime +7 -name "*.sh" -exec cp {} /data \; 查找/var/log目录中更改时间在7日以前的普通文件,并在删除之前询问它们: find /var/log -type f -mtime +7 -ok rm {} \; find /test -type f -newermt 2017-06-03 -a ! -newermt 2017-06-06 按时间范围查找/test下2017-06-03到2017-06-06之间修改过的文件
2、按用户查找
find / -user username 根据属主查找
3、按权限查找
find /tmp -type f -perm -0700 -name '*.sh' find /var/spool/postfix/public -perm /700 | xargs ls -l
-perm mode 文件的权限正好是mode就匹配 -perm -mode 文件的权限包括mode就匹配(该文件还可以拥有额外的权限属性) -perm +mode 文件的权限部分满足mode就匹配(已弃用,find新版使用-perm /mode)
4、按大小查找
find /tmp -type f -size +100k -name '*.sh'
如:删除0字节文件
find / -type f -size 0 -exec rm -rf {} \;
5、查找空目录
find /tmp -type d -empty
6、find -print0 和 xargs -0的使用
find . -name "*.txt" -print0 | xargs -0 rm find . -type f -name "*.php" -print0 | xargs -0 wc -l
xargs命令如果遇到文件名里有空格或者换行符,就会出错。因为xargs识别字符段的标识是空格或者换行符,所以如果一个文件名里有空格或者换行符,xargs就会把它识别成两个字符串,自然就出错了。
这时候就需要-print0和-0了。
find -print0表示在find的每一个结果之后加一个NULL字符,而不是默认加一个换行符。find的默认在每一个结果后加一个'\n',所以输出结果是一行一行的。当使用了-print0之后,就变成一行了。
然后xargs -0表示xargs用NULL来作为分隔符。这样前后搭配就不会出现空格和换行符的错误了。选择NULL做分隔符,是因为一般编程语言把NULL作为字符串结束的标志,所以文件名不可能以NULL结尾,这样确保万无一失。
7、按inode号
删除乱码文件,-inum
指定的是文件的 inode
号
$ ls -i 138957 a.txt 138959 T.txt 132395 ڹ��.txt $ find . -inum 132395 -exec rm {} \;
8、找出比某个文件新的文件
### 找出比test新的文件 find . -newer test ###找出比xx新,比xxx旧的文件 find . -newer test.txt ! -newer test.txt1
9、过滤目录
查找/data/web/ssy/online路径下除tmp目录之外的目录,并统计目录大小,以G位单位进行排序(默认为降序),并统计前10个大小的目录。
find /data/web/ssy/online/* -path /data/web/ssy/online/tmp -prune -o -maxdepth 0 -type d -exec /usr/bin/du -sh {} \;|grep '[0-9]G'|sort -rh|head -10
注意:
1、“-maxdepth 0” 表示只查找到/data/web/ssy/online下的目录。如果是"-maxdepth 1"则表示查找到/data/web/ssy/online/xxx下的目录
2、find命令中的过滤、忽略、排除使用 -path 过滤的文件或目录
-prune -o
,其中-prune类似于if
判断,如果-prune之前的语句为真,比如找到了前面-path指定的/data/web/ssy/online/tmp目录,就不再执行后面-o跟的语句了,如果没有找到则执行后面的语句。这样就做到了排除效果!
其中的"-o" 是 “-or” 的意思!
3、-path要过滤掉的文件或目录路径参数一定要紧跟在要搜索的路径之后
,否则过滤效果就不会实现!!也就是说上面的"-path /data/web/ssy/online/tmp"必须紧跟着放在"/data/web/ssy/online/*"后面,否则查找时就不会过滤掉/data/web/ssy/online/tmp这个目录
4、当要搜索的目录不是全路径时,要过滤掉的目录必须是"./test2"才能实现过滤效果。如果是"test2"或者"./test2/"都不能实现过滤效果
5、当要搜索的目录是全路径时,要过滤掉的目录也必须是全路径才能实现过滤效果!要过滤掉的目录后面不能加"/",否则也不能实现过滤效果
https://www.cnblogs.com/chenpingzhao/p/4623799.html xargs详解
https://www.cnblogs.com/liujunjun/p/11977906.html xargs原理及用法详解