Linux查找文件或目录 find及结合xargs应用

    find 命令主要作用是沿着文件层次结构向下遍历,匹配符合条件的文件,并执行相应的操作。Linux 下 find 命令提供了相当多的查找条件,功能很强大,如果能结合xargs等管道命令使得,更是强大无比。下面将从三个方面介绍:

1)find命令介绍及示例  (2)xargs命令介绍及示例 (3)、xargs结合find使用

闲话少絮,正文开始:

(1)find命令介绍及示例

find 命令可以根据给定的路径和表达式查找指定的文件或目录。find 参数选项很多,并且支持正则表达式,功能强大。 和管道结合使用可以实现复杂的功能,是系统管理和普通用户必须掌握的命令。 

一、find命令的格式;

find的使用格式:find path name -options [-print -exec -ok.....]

find [options] [查找路径] [查找条件][处理动作]

  默认的处理动作是显示

  其中path name表示find命令所查找的目录路径。例如用.表示当前路径,/表示系统根目录

功能:在目录结构中搜索文件,并执行指定的操作。此命令提供了相当多的查找条件,功能很强大。 

语法:find 起始目录 寻找条件 操作 

说明:find命令从指定的起始目录开始,递归地搜索其各个子目录,查找满足寻找条件的文件并对之采取相关的操作。
 

二、find命令的选项;

       1.-print表示find命令将匹配的文件输出到标准输出,

  2.-exec表示find命令对匹配的文件执行该参数给出的shell命令。相应的命令格式为‘command’ { } \;注意{}和\之间的空格。

例如:#find /tmp -atime +30 -exec rm -rf {} \;   //删除查找到的超过30天没有访问过得文件

  3.-ok和-exec的作用相同,只不过以一种更安全的模式来执行该参数所给出的shell命令,在执行每一个命令之前,都会给出一个提示,让用户来确定是否执行。

  命令选项(-option)

  1.-name 按照文件名查找文件。

  2.-perm 按照文件权限来查找

    例如:#find /tmp -prem 755     //查找在/tmp目录下权限是755的文件

         #find /tmp -prem +222  //表示只要有一类用户(属主,属组,其他)的匹配写权限就行了

         #find /tmp -prem -222   //表示必须所有类别用户都满足写权限

  3.-prune 使用这一选项可以使find命令不在当前指定的目录中查找,如果同时使用-depth选项,那么-prune将被find命令忽略。

  4.-user 按照文件的属主来查找文件。

  5.-group 按照文件所属的组来查找文件。

  6.-mtime -n +n 按照文件的更改时间来查找文件,-n表示文件更改时间距现在n天以内,+n表示文件更改的时间距现在n天以前。find命令还有-atime,-ctime(这里atime,mtime,ctime分别对应的是“最近一次访问的时间”,“最近一次内容修改的时间”和“最近一次属性修改的时间”,这里atime的单位是天)

    例如:#find /tmp -atime +5  //表示查找在五天内没有访问过得文件

            #find /tmp -atime -5   //表示查找在五天内访问过得文件

  7.-nogroup 查找无有效所属组的文件,即该文件所属组在/etc/group中不存在。

  8.-nouser 查找无有效属组的文件,即该文件在/etc/paawd中不存在。

  9.-newer file1 !file2 查找比file1新但是比file2旧的文件。

  10.-type 查找某一类型的文件例如

    b - 块设备文件

    d -目录

    c -字符设备文件

    p - 管道文件

    l - 符号链接文件

      f - 普通文件

  11. -size n:[c] 查找文件长度为n快的文件,有时带有c时表示文件长度以字节记

    例如:#find /tmp -size 2M     //查找在/tmp目录下等于2M的文件

         #find /tmp -size +2M  //查找在/tmp目录下大于2M的文件

         #find /tmp -size -2M   //查找在/tmp目录下小于2M的文件

  12. -depth:查找文件时,首先查找当前目录中的文件,然后再其中子目录中查找。

        13. find 还支持正则表达式查找

    find /data/logs -mame "*.log"  -type f -printf    查找符合指定字符串的文件
 find . -name "[0-9]" -type f   查找以数字开头的文件
 find / -mtime -1 |head  查找系统内最近24小时修改过的文件
    find / -mmin  -15 |head   查找系统内最近15 分钟修改过的文件

-a and -o and -not的使用:

-a链接两个不同的条件(两个条件必须同时满足)

  例如:#find /tmp -name "*.sh" -a -user root  //查找文件名为*.sh并且用户是root的文件

-o链接两个不同的条件(两个条件满足其一即可)

  例如:#find /tmp -name "*.sh" -a -user root

-not对条件取反的

  例如:#find /tmp -not -user root     //查找用户不是根目录下的文件

我的示例:

[work@haibi-dx 666]$ ll -R

.:

total 8

-rw-rw-r-- 1 work work 28 Feb 24 22:29 abc.txt

drwxrwxr-x 2 work work 46 Feb 24 22:36 log

-rw-rw-r-- 1 work work 26 Feb 24 22:34 one.txt

./log:

total 8

-rw-rw-r-- 1 work work 23 Feb 24 22:36 555.txt

-rw-rw-r-- 1 work work 28 Feb 24 22:29 efg.log

[work@haibi-dx 666]$ find ./ -name '*txt' -o -name '*log'

./abc.txt

./log

./log/efg.log

./log/555.txt

./one.txt

[work@haibi-dx 666]$ find ./ -name '*txt' -o -name '*.log'

./abc.txt

./log/efg.log

./log/555.txt

./one.txt

[work@haibi-dx 666]$ find ./ -name 'efg*' -a -name '*.log'

./log/efg.log

[work@haibi-dx 666]$ find ./ -name '*txt' -o -name '*log'

./abc.txt

./log

./log/efg.log

./log/555.txt

./one.txt

[work@haibi-dx 666]$ find ./ -name '*txt' -not -name '*log'

./abc.txt

./log/555.txt

./one.txt

参考:https://www.cnblogs.com/qingjiaowoxiaoxioashou/p/6270474.html

(2)、xargs命令介绍及示例

       xargs是给命令传递参数的一个过滤器,也是组合多个命令的一个工具。它把一个数据流分割为一些足够小的块,以方便过滤器和命令进行处理。通常情况下,xargs从管道或者stdin中读取数据,但是它也能够从文件的输出中读取数据。xargs的默认命令是echo,这意味着通过管道传递给xargs的输入将会包含换行和空白,不过通过xargs的处理,换行和空白将被空格取代。

      在使用 find命令的-exec选项处理匹配到的文件时, find命令将所有匹配到的文件一起传递给exec执行。但有些系统对能够传递给exec的命令长度有限制,这样在find命令运行几分钟之后,就会出现溢出错误。错误信息通常是“参数列太长”或“参数列溢出”。这就是xargs命令的用处所在,特别是与find命令一起使用。  

      find命令把匹配到的文件传递给xargs命令,而xargs命令每次只获取一部分文件而不是全部,不像-exec选项那样。这样它可以先处理最先获取的一部分文件,然后是下一批,并如此继续下去。

xargs 是一个强有力的命令,它能够捕获一个命令的输出,然后传递给另外一个命令。

最经典应用模式:  somecommand |xargs -item  command   

不带command ,默认的使用echo 输出

[root@auc-test2 log]#  find . -name '*txt' | xargs
./abc.txt ./log/555.txt ./one.txt ./test.txt
 

用途:

    1.构造参数列表并运行命令,即将接收的参数传递给后面的command 命令执行

    2.将多行输入转换为单行 (特殊功效)

优点:

       1. 将输入参数整理后,去除换行符,以一个列表形式处理

       2. 避免参数过长引发的问题,使用xargs -n 参数适当控制,对于经常产生大量输出的命令如find、locate和grep来说非常有用

XARGS 一般是和管道一起使用: 

XXcomand  | xargs  -x  comand initial-args

-x 代表选项

xargs用作替换工具,读取输入数据重新格式化后输出。
定义一个测试文件,内有多行文本数据:

[work@haibi-prd-dx 666]$ cat test.txt
a b c d e f g
h i j k l m n
o p q
r s t
u v w x y z

多行输入单行输出:
[work@haibi-prd-dx 666]$ cat test.txt | xargs
a b c d e f g h i j k l m n o p q r s t u v w x y z
-n选项多行输出:
[work@haibi-prd-dx 666]$ cat test.txt | xargs -n 3
a b c
d e f
g h i
j k l
m n o
p q r
s t u
v w x
y z
[work@haibi-prd-dx 666]$ cat test.txt | xargs -n 5
a b c d e
f g h i j
k l m n o
p q r s t
u v w x y
z

-d选项可以自定义一个定界符:

echo "nameXnameXnameXname" | xargs -dX
name name name name
结合-n选项使用:
echo "nameXnameXnameXname" | xargs -dX -n2
name name
name name

读取stdin,将格式化后的参数传递给命令

假设一个命令为 sk.sh 和一个保存参数的文件arg.txt:

[work@haibian-mp-hadoop06-prd-dx 666]$ more sk.sh
#!/bin/bash
echo $*

arg.txt文件内容:
cat arg.txt
aaa
bbb
ccc

xargs的一个选项-I,使用-I指定一个替换字符串{},这个字符串在xargs扩展时会被替换掉,当-I与xargs结合使用,每一个参数命令都会被执行一次:

[work@haibian-mp-hadoop06-prd-dx 666]$ ll
total 16
drwxrwxr-x 2 work work 46 Feb 24 22:36 log
-rw-rw-r-- 1 work work 20 Feb 24 23:42 sk.sh
-rw-rw-r-- 1 work work 52 Feb 24 23:43 arg.txtt

[work@haibi 666]$ cat ./arg.txt | xargs -I {} ./sk.sh -p {} -l
xargs: ./sk.sh: Permission denied
[work@haibi 666]$ chmod a+x sk.sh
[work@haibi 666]$ cat ./arg.txt | xargs -I {} ./sk.sh -p {} -l
-p aaa -l
-p bbb -l
-p ccc -l


复制所有图片文件到 /data/images 目录下:
ls *.jpg | xargs -n1 -I cp {} /data/images

xargs的一些有用的选项

相信到这里应该都知道xargs的作用了,那么我们看看xargs还有一些有用的选项:

1. -d 选项
默认情况下xargs将其标准输入中的内容以空白(包括空格、Tab、回车换行等)分割成多个之后当作命令行参数传递给其后面的命令,并运行之,我们可以使用 -d 命令指定分隔符,例如:
echo '11@22@33' | xargs echo 
输出:
11@22@33
默认情况下以空白分割,那么11@22@33这个字符串中没有空白,所以实际上等价于 echo 11@22@33 其中字符串 '11@22@33' 被当作echo命令的一个命令行参数

echo '11@22@33' | xargs -d '@' echo 
输出:
11 22 33
指定以@符号分割参数,所以等价于 echo 11 22 33 相当于给echo传递了3个参数,分别是11、22、33

2. -p 选项
使用该选项之后xargs并不会马上执行其后面的命令,而是输出即将要执行的完整的命令(包括命令以及传递给命令的命令行参数),询问是否执行,输入 y 才继续执行,否则不执行。这种方式可以清楚的看到执行的命令是什么样子,也就是xargs传递给命令的参数是什么,例如:
echo '11@22@33' | xargs -p -d '@'  echo 
输出:
echo 11 22 33
 ?...y      ==>这里询问是否执行命令 echo 11 22 33 输入y并回车,则显示执行结果,否则不执行
 11 22 33   ==>执行结果

3. -n 选项
该选项表示将xargs生成的命令行参数,每次传递几个参数给其后面的命令执行,例如如果xargs从标准输入中读入内容,然后以分隔符分割之后生成的命令行参数有10个,使用 -n 3 之后表示一次传递给xargs后面的命令是3个参数,因为一共有10个参数,所以要执行4次,才能将参数用完。例如:

echo '11@22@33@44@55@66@77@88@99@00' | xargs -d '@' -n 3 echo 
输出结果:
11 22 33
44 55 66
77 88 99
00
等价于:
echo 11 22 33
echo 44 55 66
echo 77 88 99
echo 00
实际上运行了4次,每次传递3个参数,最后还剩一个,就直接传递一个参数。

4. -E 选项,有的系统的xargs版本可能是-e  eof-str
该选项指定一个字符串,当xargs解析出多个命令行参数的时候,如果搜索到-e指定的命令行参数,则只会将-e指定的命令行参数之前的参数(不包括-e指定的这个参数)传递给xargs后面的命令
echo '11 22 33' | xargs -E '33' echo 
输出:
11 22

可以看到正常情况下有3个命令行参数 11、22、33 由于使用了-E '33' 表示在将命令行参数 33 之前的参数传递给执行的命令,33本身不传递。等价于 echo 11 22 这里-E实际上有搜索的作用,表示只取xargs读到的命令行参数前面的某些部分给命令执行。

注意:-E只有在xargs不指定-d的时候有效,如果指定了-d则不起作用,而不管-d指定的是什么字符,空格也不行。

echo '11 22 33' | xargs -d ' ' -E '33' echo  => 输出 11 22 33
echo '11@22@33@44@55@66@77@88@99@00 aa 33 bb' | xargs -E '33' -d '@' -p  echo  => 输出 11 22 33 44 55 66 77 88 99 00 aa 33 bb

## -0 选项表示以 '\0' 为分隔符,一般与find结合使用

find . -name "*.txt"
输出:
./2.txt
./3.txt
./1.txt     => 默认情况下find的输出结果是每条记录后面加上换行,也就是每条记录是一个新行

find . -name "*.txt" -print0
输出:
./2.txt./3.txt./1.txt     => 加上 -print0 参数表示find输出的每条结果后面加上 '\0' 而不是换行

find . -name "*.txt" -print0 | xargs -0 echo 
输出:
./2.txt ./3.txt ./1.txt

find . -name "*.txt" -print0 | xargs -d '\0' echo 
输出:
./2.txt ./3.txt ./1.txt

xargs的 -0 和 -d '\0' 表示其从标准输入中读取的内容使用 '\0' 来分割,由于 find 的结果是使用 '\0' 分隔的,所以xargs使用 '\0' 将 find的结果分隔之后得到3个参数: ./2.txt ./3.txt ./1.txt  注意中间是有空格的。上面的结果就等价于 echo ./2.txt ./3.txt ./1.txt

实际上使用xargs默认的空白分隔符也是可以的  find . -name "*.txt"  | xargs  echo   因为换行符也是xargs的默认空白符的一种。find命令如果不加-print0其搜索结果的每一条字符串后面实际上是加了换行

[work@hai-dx 666]$ find . -name '*txt' | xargs -echo
./abc.txt ./log/555.txt ./one.txt ./test.txt ./arg.txt
[work@hai 666]$ find . -name '*txt' | xargs echo
./abc.txt ./log/555.txt ./one.txt ./test.txt ./arg.txt

(3)、xargs结合find使用

       find命令可以把匹配到的文件传递给 xargs 命令执行,在使用 find 命令的 -exec 选项处理匹配到的文件时,find将所有匹配到的文件一起传递给 exec 执行。由于有些系统对能够传递给 exec 的命令长度有限制,这样会引起溢出错误。这时可以使用 xargs 命令。

       find . -type f -name "*.log" -print0 | xargs -0 rm -f #xargs -0将\0作为定界符
       find . -type f -name "*.php" -print0 | xargs -0 wc -l #统计一个源代码目录中所有php文件的行数
       find . -type f -name "*.jpg" -print | xargs tar -czvf images.tar.gz #查找所有的jpg 文件,并且压缩它们
  find / -type f -print | xargs file    查找系统中的每一个普通文件,并用 file 命令来测试它们分别属于哪一类文件。
  find . -type f -name "\.log" -print | xargs rm  查找当前目录下的 .log 文件,并删除 。
  find . -type f -exec ls -l {} \;  用 ls -l 列出所有匹配到的文件。
  find logs  -type f -mtime +5 -exec rm {} \;  查找 log 中更改时间在 5 天前的文件并删除。
  find logs -type f -ok rm {} \;  查找 log中的所有普通文件并在删除前确认。  
  find . -type f -name "\.log" -print | gerp "node"     查找当前目录下的 .log 文件,并从查找结果中筛选出带有 node 字符串的文件 。

参考:https://www.cnblogs.com/wangqiguo/p/6464234.html 

           https://blog.csdn.net/bbwangj/article/details/82871320

xargs命令详解,xargs与管道的区别

你可能感兴趣的:(Linux,文件操作)