• Linux那点事xargs命令详解


    1. 为什么需要xargs命令

    1.1 管道|的缺陷

    管道实现的是将前面的输出stdout作为后面的输入stdin,但是有些命令不接受管道的传递方式。例如:ls,这是为什么呢?

    因为有些命令希望管道传递过来的是参数,但是直接使用管道有时无法传递到命令的参数位这时候就需要xargsxargs实现的是将管道传递过来的stdin进行处理然后传递到命令的参数位置上。

    用户查找文件:

    用户希望处理查找后的文件:

     
    管道的缺陷

    也就是xargs完成了两个行为:

    1. 处理管道传输过来的stdin
    2. 将处理后的数据传递到正确的位置;

    1.2 xargs对数据的处理

    处理大量数据的时候,可能会发生参数列表过长的情况。而xargs将完成参数的定位我们清楚,但是xrags如何处理管道传输的stdin呢?

    其实就是完成两个操作:

    1. 对数据的分割;
    2. 对数据的分批;

    xargs处理的优先级或顺序:先分割,在分批,然后传递到参数位。

    可以设想一个场景,我想对一堆数据进行处理,实际上是对一堆中的每个数据进行分别的处理。那么如何将一堆数据按照自定义规则分割为独立的数据?若是一次性传递的数据过多,又该如何处理?

    1.2.1 xrags的并发处理

    但需要注意的是,尽管实现了分批处理,但是默认情况下并没有提高任何效率,因为分批传递之后还是一次执行一个。而且有时候分批之后是将其作为一个参数的整体,并不会将分批中的信息分段执行。

    但事实上,xargs提供-P选项,用于指定并发执行的数量(默认是只要一个处理进程,不会提供效率,但是可以指定为N个子进程,或者指定为0表示尽可能多的利用CPU)。这样就能将让分批操作更好的利用多核CPU,从而提升效率。例如上面分成了两批,指定-P 2可以并发执行两批,而并非执行完第一批之后再执行第二批。

    剩下的功能就是处理xargs的细节问题了,比如如何分割(xargs、xargs -d、xargs -0),分割后如何划批(xargs -n、xargs -L),参数如何传递(xargs -i)。另外xargs还提供了询问交互处理(-p选项)和预先打印一遍命令执行情况(-t选项),传递终止符(-E选项)等。

    1.2.2 执行命令准备

    命令准备:

    [root@xuexi tmp]$ cd /tmp
    [root@xuexi tmp]$ rm -fr *
    [root@xuexi tmp]$ mkdir a b c d test logdir shdir
    [root@xuexi tmp]$ touch "one space.log"
    [root@xuexi tmp]$ touch logdir/{1..10}.log
    [root@xuexi tmp]$ touch shdir/{1..5}.sh
    [root@xuexi tmp]$ echo "the second sh the second line" > shdir/2.sh 
    [root@xuexi tmp]$ cat <<eof>shdir/1.sh  
    > the first sh
    > the second line
    > eof
    

    1.2.3 Linux空格含义

    那么按照什么规则进行“分割”以及“分批”呢?

    Linux文件空格分类(重点):

     
    换行符、制表符、空格符
    • 正方形(\t)代表:(标记意义)制表符;
    • 圆形(空格)代表:(文本意义)普通空格;
    • 长方形(\n)代表:(标记意义)换行符;
     
    文本意义换行符和标记意义换行符
    • 椭圆形代表:(文本意义)换行符;
    • 长方形代表:(标记意义)换行符;

    2. xrags的分割行为

    xargs命令会将接收的stdin所有的空白(空格、制表符、换行符)都转换为空格。我们使用xargs -d "xx"自定义规则对数据进行切分。默认情况下,xargs使用空格来切分数据。

    注意事项

    • xargs -d可以指定分割符,可以是单个符号、字母或者数字。如指定o为分割符:xargs -d "o"
    • xargs -d是分割阶段的选项,所以会优先于分批选项(-n、-L、-i)
    • xargs -d不是先xargs-d处理的,它是区别于独立的xargs的另外一个分割选项。

    1. xargs -d原理

    • 替换:将接收stdin所有的【标记意义】的符号替换为\n,替换完成后所有的符号(空格、制表符、分行符)变成【文本意义】上的普通符号。

    • 分段:根据-d指定的分隔符进行分段,并用空格分开每段,由于发生了【替换】操作,所以符号都是【文本意义】上的。会导致分段中可能包含了空格、制表符、分行符。也就是说处了-d导致的【分段空格】,其余所有符号都是分段中的一部分。

    • 输出:最后根据指定的【分批选项】来输出。

    2. 案例分析

    默认情况下,使用空格进行分割,但若是指定自定义分割符(此处使用o),那么将o替换为分段空格后,切分独立整体。

    使用-d分段

    xargs -d "o"进行自定义分割后,然后分批,我们可以看到,实际上分成了2批。

     
    使用-n查看-d的分批情况

    3. xrags -0命令

    xargs -0的行为和xargs -d基本一样,只是-d是指定分割符,-0是指定固定的\0作为分割符。等价于xargs -d "\0"

    (注意)xargs -0 可以处理接收到的stdin中的null字符(\0)。如果不使用-0选项或-null选项,检测到\0后会给出警告提醒,并只向命令传递非\0段。

    tr命令:替换或者删除字符】

     
    \0的作用

    4. 实际应用:
    -xargs -0的包含空格的文件的操作。

    【起因】使用find+rm命令无法删除带有空格的文件。

     
    xargs命令输出

    【原因】:xargs默认是以空白字符(空格、换行符、制表符)来分割记录的实际上rm删除的数据便是./onefile.txt

    【解决方案】:此时我们不能使用默认的分割符,而应该使用自定义的分割符!我们知道find命令,文件后面均是换行符

     
    find命令

    【解决方案】为了解决这个问题,可以在每个文件将换行符替换为NULL(\0)。这样我们以\0分割,就可以得到完整文件。

    xargs -0分段

    为什么要使用\0作为分割符,而不是其他字符呢?因为在编程语言中,一般使用\0作为结束标志。而文件的路径名不可能包含\0

    本质上是借助xargs的对\0的分割操作。find命令将换行符替换成\0。

    3. xargs的分批行为

    对于xargs,不写命令时默认的执行是echo

     
    默认xargs命令将换行处理掉了

    将换行处理掉不是echo实现的,而是管道传递过来的stdin经过xargs处理后得到的。将所有【文本/标记意义】空格、制表符和分行符都替换为【文本意义】上空格并压缩到一行显示。

    【注意】这一整行将作为一个整体。这个整体可能直接交给命令或者作为stdout通过管道传递给管道右边的命令,这时结果将作为一个整体传递,也有可能被xargs同时指定的【分批选项】分批处理。(这也是可能出现参数列表过长的原因)

    xargs分批命令总结:

    • xargs -n :和独立的xargs命令配合使用时,按照默认分割符(空格)进行分批,但配合xargs -d命令,则按自定义分割符分批。

    • xargs -L-n选项类似,唯一的区别就是-L永远是按段划批,而-n和独立的xargs一起使用时是按空格分段划批的。

    2. 对独立的xargs指定分批选项

    • 【标记/文本】指定-n时按空格分段,然后划批,不管是文本意义空格还是标记意义的空格,只要是空格都是-n的操作对象。

    • 【标记】指定-L或者-i时按段划批,文本意义的符号不被处理。

    【需要注意的是】:【xargs -n】本质上分为两种情况:

    1. 和独立的xargs一起使用,这时按照每个空格分段划批;
    2. xargs -dxargs -0一起使用,这时按段分批;
    3. xargs -L-n选项类似,唯一的区别就是-L永远是按段划批,而-n和独立的xargs一起使用时是按空格分段划批的。
     
    -n和-L的区别
     
    -i也不会分割文本意义的空格

    4 xargs -i 接收传递的分批结果

    xargs -i选项在逻辑上用于接收传递的分批结果。

    如果不使用-i,则默认是将分割处理后的结果整体传递到【命令的最尾部】。但是有时候需要传递到多个位置,不使用-i就不知道传递到哪个位置了。

    例如:重命名备份的时候在每个传递过来的文件名加上后缀.bak,这需要两个参数位。

    语法:
    使用xargs -i时以大括号{}作为替换符号,传递的时候看到{}就将结果替换,可以将{}放在任意需要传递的参数位置上。如果多个地方使用{}就实现了多个传递。

    xargs -Ixargs -i是一样的,只是-i默认使用大括号作为替换符号,-I可以指定其他符号、字母、数字作为替换符号,但是必须用引号包起来。man推荐使用-I代替-i,但是一般使用-i方便,除非在命令中不能使用{},例如touch {1...10}.log时,大括号就不能用来做替换符号。

    分析:重命名备份的时候在每个传递过来的文件名加上后缀.bak

    案例分析1:

    ./指的是当前目录】

    1. 重命名逻辑是:mv ./logdir/a.log ./logdir/a.log.bak
    2. 我们想将一个目录下的文件都要执行某些逻辑。

    命令:ls logdir/ | xargs -i mv ./logdir/{} ./logdir/{}.bak

    为什么将“-i”选项划分在分批选项里面,因为它默认一个段就是一个批,每次传递一个批就是传递一个段到指定大括号{}位上。不理解,可以看下1.2.4 分批选项的生效规则

     
    xargs的-i字段的使用

    案例分析2:

    例如:想将数字1-10没三个数显示在startend之间。

    start 1 2 3 end 
    start 4 5 6 end 
    start 7 8 9 end 
    start 10 end 
    

    由于指定了参数传递位置,所以必须使用-i,那就无法一次传递3个数,要解决这个问题,就要想办法让每三个树分一次段,然后后使用-i传递,那么可以将每三个数分一次行写入一个文件。
    例如:

     
    xargs -i分段操作

     

    当然,也可以多次使用xargs。在很多使用无法解决分段的问题都可以通过多次使用xargs来解决。

     
    多次使用xargs命令进行分段

    5. 分批选项的生效规则

    -i、-L、-n选项都是分批选项,他们的生效规则是:谁指定在后面,谁就生效!!!

     
    -i在-n之后,-n将被忽略

    实际上,-i就是隐含了-L 1-i分批并传递这两个作用跟严格些。


    6. xargs观察命令的执行过程

    使用-p选项是交互询问式的,只有每次询问的时候输入y(或者yes)才会执行,直接按entry键是不会执行的。

    使用-t选项是在每次执行xargs后面的命令都会先在stderr上打印一遍命令的执行过程然后才正式执行。

    使用-p-t选项就可以根据xargs后面的命令的执行顺序进行推测,xargs是如何分段,分批以及传递的。

     
    -p或者-t参数如何使用

    【后续】 分批选项的的典型应用

    1. 同一目录下文件过多

    分批选项有时特别有用,例如脚本规定每次只能传递三个参数,有时候grep或者rm -rf文件数量特别多的时候会提示参数列表过长而导致失败,这时候就可以分批来按批查询或删除。
    命令:ls | xargs -n 10000 rm -rf

    2. xargs+find的使用

    xargs原本就是为find而开发的。

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

    实际应用:

    ls+grep跨目录查询时,我们将文件通过管道输入到grep参数处,此时并没有包含目录地址,边会出现下面的错误。

     
    ls + grep 跨目录查询

    解决方案:

    find找到的文件地址传递给grep命令的参数处。

     
     
    find+grep



  • 相关阅读:
    BeagleBone Black安装小米随身WiFi驱动方法
    java-ee,ssh整合博文收藏
    BeagleBoneBlack Linux开发相关链接收藏
    Debian7.7 wheezy 中源码安装emacs24
    GLOG使用注意事项
    centos、linux改变ll命令显示颜色
    centos中samba配置后始终连不上的绝招
    中兴电信光纤猫F612管理员密码获取方法
    STM32W108芯片的SWD在IAR7.30版本中不能用
    TRF7960天线参数试验
  • 原文地址:https://www.cnblogs.com/chenxiaomeng/p/16040498.html
Copyright © 2020-2023  润新知