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/