xargs命令

xargs命令


今天在使用find 命令的时候想将查找的结果进行处理,然后就想到了find的用法 exec和xargs这两个参数;
不过在使用find --help时发现xargs并不是find的参数,我猜想xargs是一条独立的命令;
百度到一条重要信息,find不支持管道命令

之前一直认为管道命令无敌,百度到这个结果后管道"|"在我心中的形象突然崩塌

言归正传:
一、管道命令
  重新认识下管道命令:
    管道命令操作符是:”|”,它仅能处理经由前面一个指令传出的正确输出信息,也就是 standard output 的信息,
    对于 stdandard error 信息没有直接处理能力。然后,传递给下一个命令,作为标准的输入 standard input.

  
    command1正确输出,作为command2的输入 然后comand2的输出作为,comand3的输入 ,comand3输出就会直接显示在屏幕上面了。
    通过管道之后:comand1,comand2的正确输出不显示在屏幕上面
  注意:
    1、管道命令只处理前一个命令正确输出,不处理错误输出
    2、管道命令右边命令,必须能够接收标准输入流命令才行。


  实例

/home目录下只有1.txt cassandra a.txt scripts test.sh test1.sh b.txt几个文件,没有test2.sh文件
[root@localhost home]# cat test1.sh | ls
1.txt cassandra chazhaomulu.txt scripts test.sh test1.sh tihuanmubiao.txt

[root@localhost home]# cat test1.sh 
line1
line2
line3
line4
echo "very good!";
line6
echo "good!";
line8
echo "pass!";
line10
echo "no pass!";

[root@localhost home]# cat test1.sh | grep -n 'echo'
5:	echo "very good!";
7:	echo "good!";
9:	echo "pass!";
11:	echo "no pass!";
#读出test1.sh文件内容,通过管道转发给grep 作为输入内容

[root@localhost home]# cat test1.sh test2.sh | grep -n 'echo'
cat: test2.sh: No such file or directory
5:	echo "very good!";
7:	echo "good!";
9:	echo "pass!";
11:	echo "no pass!";
#cat test2.sh不存在,错误输出打印到屏幕,正确输出通过管道发送给grep 

[root@localhost home]# cat test1.sh test2.sh 2>/dev/null | grep -n 'echo'
5:	echo "very good!";
7:	echo "good!";
9:	echo "pass!";
11:	echo "no pass!";
#将test2.sh 没有找到错误输出重定向输出给/dev/null 文件,正确输出通过管道发送给grep

[root@localhost home]# cat test1.sh | ls
1.txt cassandra a.txt scripts test.sh test1.sh b.txt

  

    #读取test1.sh内容,通过管道发送给ls命令,由于ls 不支持标准输入,因此数据被丢弃
    管道沟通的是 标准输入输出(stdin/stdout),ls命令接受的路径是 命令行参数 。(读取的是命令行参数,而不是 stdin。)
    上面例子中cat test1.sh | ls,目的是用ls列出file(test1.sh)文件中的每一行路径的内容。
    ls是以类似ls /path/to/file这种方式调用的,你需要的不是管道,而是ls $(cat file)
    相当多命令是同时可以接受两者的,容易造成混乱;
    cat/ls只支持命令行参数。但没有人规定一定要同时支持两者。

    例子:
    vim编辑文件时用的命令是vim file,但如果要从stdin读入编辑内容的话就需要使用echo "gagagagaggaga" | vim -。
    在vim后面加上一个参数-来告诉vim调整行为,改为从stdin读入内容。

    PS:
    遇到这种命令就需要使用xargs了;
    查看一个命令是否支持stdin,看man(--help)就可以了
    example:
    ls:List information about the FILEs (the current directory by default).
    wc:With no FILE, or when FILE is -, read standard input.


    cat file|awk -f script #(UUOC)效果上与
    awk -f script file 一样。
    关于管道命令与重定向区别、shell脚本接收管道输入:


二、xargs命令
  1.关于xargs的描述

    xargs 读入stdin的数据,并且以空格符或断行符进行分辨,将stdin的数据分隔为arguments
    xargs命令是给其他命令传递参数的一个过滤器,也是组合多个命令的一个工具。
    它擅长将标准输入数据转换成命令行参数,xargs能够处理管道或者stdin并将其转换成特定命令的命令参数。
    xargs也可以将单行或多行文本输入转换为其他格式,例如多行变单行,单行变多行。
    xargs的默认命令是echo,空格是默认定界符。
    这意味着通过管道传递给xargs的输入将会包含换行和空白,不过通过xargs的处理,换行和空白将被空格取代。
    xargs是构建单行命令的重要组件之一
  2.选项解释

-0 当sdtin含有特殊字元时候,将其当成一般字符,像\'空格等
例如:	[root@localhost home]# echo "\\"|xargs echo


[root@localhost home]# echo "\\"|xargs -0 echo
\

-a file 从文件中读入作为sdtin
-e flag ,注意有的时候可能会是-E,flag必须是一个以空格分隔的标志,当xargs分析到含有flag这个标志的时候就停止。
-p 当每次执行一个argument的时候询问一次用户。
-n num 后面加次数,表示命令在执行的时候一次用的argument的个数,默认是用所有的。
-t 表示先打印命令,然后再执行。
-i 或者是-I,这得看Linux支持了,将xargs的每项名称,一般是一行一行赋值给{},可以用{}代替。
-r no-run-if-empty 当xargs的输入为空的时候则停止xargs,不用再去执行了。
-s num 命令行的最好字符数,指的是xargs后面那个命令的最大命令行字符数。	
-L num Use at most max-lines nonblank input lines per command line.-s是含有空格的。
-l 同-L
-d delim 分隔符,默认的xargs分隔符是回车,argument的分隔符是空格,这里修改的是xargs的分隔符
-x exit的意思,主要是配合-s使用。
-P 修改最大的进程数,默认是1,为0时候为as many as it can ,这个例子我没有想到,应该平时都用不到的吧。

  

  3.xargs命令用法

    xargs用作替换工具,读取输入数据重新格式化后输出。

(a)
定义一个测试文件,内有多行文本数据:
[root@localhost home]# 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

(b)
多行输入单行输出:
[root@localhost home]# 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

(c)
-n选项多行输出:
[root@localhost home]# cat test.txt | xargs -n3
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)
-d选项可以自定义一个定界符:
[root@localhost home]# echo "nameXnameXnameXname" | xargs -dX
name name name name
结合-n选项使用:
[root@localhost home]# echo "nameXnameXnameXname" | xargs -dX -n2
name name
name name


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

假设一个命令为 sk.sh 和一个保存参数的文件arg.txt:(需要加执行权限)
#!/bin/bash
#sk.sh命令内容,打印出所有参数。
echo $* 

arg.txt文件内容:

cat arg.txt
aaa
bbb
ccc

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

cat arg.txt | xargs -I {} ./sk.sh -p {} -l
-p aaa -l
-p bbb -l
-p ccc -l

<2>
复制所有图片文件到 /data/images 目录下:

ls *.jpg | xargs -n1 -I cp {} /data/images
#
(h)
xargs结合find使用

用rm 删除太多的文件时候,可能得到一个错误信息:/bin/rm Argument list too long. 用xargs去避免这个问题:

find . -type f -name "*.log" -print0 | xargs -0 rm -f

xargs -0:当sdtin含有特殊字元时候,将其当成一般字符,像\'空格等;
防止名称中包含空格等特殊字符
/**注释
Items are separated by a null, not whitespace.Disables quote and backslash processing
项目被Null而不是空格分隔开,禁用引用和反斜杠处理
**/

统计一个源代码目录中所有php文件的行数:

find . -type f -name "*.php" -print0 | xargs -0 wc -l

查找所有的jpg 文件,并且压缩它们:

find . -type f -name "*.jpg" -print | xargs tar -czvf images.tar.gz
(i)
xargs其他应用

假如你有一个文件包含了很多你希望下载的URL,你能够使用xargs下载所有链接:

cat url-list.txt | xargs wget -c

  

  3.子Shell(Subshells)
    运行一个shell脚本时会启动另一个命令解释器.,就好像你的命令是在命令行提示下被解释的一样,类似于批处理文件里的一系列命令。
    每个shell脚本有效地运行在父shell(parent shell)的一个子进程里。
    这个父shell是指在一个控制终端或在一个xterm窗口中给你命令指示符的进程。

    cmd1 | ( cmd2; cmd3; cmd4 ) | cmd5

    如果cmd2 是cd /,那么就会改变子Shell的工作目录,这种改变只是局限于子shell内部,cmd5则完全不知道工作目录发生的变化。
    子shell是嵌在圆括号()内部的命令序列,子Shell内部定义的变量为局部变量。 子shell可用于为一组命令设定临时的环境变量:

    COMMAND1
    COMMAND2
    COMMAND3
    (
      IFS=:
      PATH=/bin
      unset TERMINFO
      set -C shift 5
      COMMAND4
      COMMAND5
      exit 3 # 只是从子shell退出。
    )
    # 父shell不受影响,变量值没有更改。
    COMMAND6
    COMMAND7

 更多xargs补充:http://blog.csdn.net/zhangfn2011/article/details/6776925/

posted @ 2017-05-27 16:45  陈浩然201  阅读(458)  评论(0编辑  收藏  举报