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 | ls1.txt cassandra chazhaomulu.txt scripts test.sh test1.sh tihuanmubiao.txt[root@localhost home]# cat test1.sh line1line2line3line4echo "very good!";line6echo "good!";line8echo "pass!";line10echo "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 directory5: 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 | ls1.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 gh i j k l m no p qr s tu v w x y z(b)多行输入单行输出:[root@localhost home]# cat test.txt | xargsa 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 -n3a b cd e fg h ij k lm n op q rs t uv w xy z(d)-d选项可以自定义一个定界符:[root@localhost home]# echo "nameXnameXnameXname" | xargs -dXname name name name结合-n选项使用:[root@localhost home]# echo "nameXnameXnameXname" | xargs -dX -n2name namename name(e)读取stdin,将格式化后的参数传递给命令假设一个命令为 sk.sh 和一个保存参数的文件arg.txt:(需要加执行权限)#!/bin/bash#sk.sh命令内容,打印出所有参数。echo $* arg.txt文件内容:cat arg.txtaaabbbccc<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 -fxargs -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补充: