linux下xargs命令用法详解
(1)find命令是根据文件的属性进行查找,如文件名,文件大小,所有者,所属组,是否为空,访问时间,修改时间等。
(2)grep是根据文件的内容进行查找,会对文件的每一行按照给定的模式(patter)进行匹配查找。
(3)find命令把匹配到的文件传递给xargs命令,而xargs命令每次只获取一部分文 件而不是全部,不 像-exec选项那样。这样它可以先处理最先获取的一部分文件,然后是下一批,并如此继续下去。 在有些系统中,使用-exec选项会为处理每一个匹配到的文件而发起一个相应的进程,并非将匹配 到的文件全部作为参数一次执行;这样在有些情况下就会出现进程过多,系统性能下降的问题, 因而效率不高;而使用xargs命令则只有一个进程。另外,在使用xargs命令时,究竟是一次获取所有的参数,还 是分批取得参数,以及每一次获取参数的数目都会根据该命令的选项及系统内核中相应的可调参数来确定。
2.find用法:
(1)find /tmp -size +10000c -and -mtime +2 #在/tmp目录下查找大于10000字节并在最后2分钟内修改的文件
(2)find / -user fred -or -user george #在/目录下查找用户是fred或者george的文件文件
(3)find /tmp ! -user panda #在/tmp目录中查找所有不属于panda用户的文件
3.grep用法:
(1)grep 'test' d* #显示所有以d开头的文件中包含 test的行
(2)grep ‘test’ aa bb cc #显示在aa,bb,cc文件中包含test的行
(3)grep ‘[a-z]\{5\}’ aa #显示所有包含每行字符串至少有5个连续小写字符的字符串的行
(4)grep magic /usr/src #显示/usr/src目录下的文件(不含子目录)包含magic的行
(5)grep -r magic /usr/src #显示/usr/src目录下的文件(包含子目录)包含magic的行
(6)grep -w pattern files :只匹配整个单词,而不是字符串的一部分(如匹配’magic’,而不是’magical’),
(7)grep 'hello' $(find . -name *.c) -i
(8)grep 'hello' ./yuhaojin/*.c -i -n
4.find & grep 使用方法
(1).从根目录开始查找所有扩展名为.log的文本文件,并找出包含”ERROR”的行
find / -type f -name "*.log" | xargs grep "ERROR"
(2).例子:从当前目录开始查找所有扩展名为.in的文本文件,并找出包含”thermcontact”的行
find . -name "*.in" | xargs grep "thermcontact"
5.find & xargs使用方法
(1).find . -type f -print | xargs file
查找系统中的每一个普通文件,然后使用xargs命令来测试它们分别属于哪类文件
(2).find / -name “core” -print | xargs echo “” >/tmp/core.log
在整个系统中查找内存信息转储文件(core dump) ,然后把结果保存到/tmp/core.log 文件中:
(3).find . -type f -print | xargs grep “hostname”
用grep命令在所有的普通文件中搜索hostname这个词
(4).find ./ -mtime +3 -print|xargs rm -f –r
删除3天以前的所有东西 (find . -ctime +3 -exec rm -rf {} ;)
(5)find ./ -size 0 | xargs rm -f &
删除文件大小为零的文件
(6)find命令配合使用exec和xargs可以使用户对所匹配到的文件执行几乎所有的命令。
重定向的方法如下:
> filename,重定向标准输出到文件,覆盖文件。
>> filename,重定向标准输出到文件,追加模式。
2> filename,重定向标准错误到文件。
&> filename,重定向标准输入和标准错误到文件。相当于同时使用>和2>。(感谢yszzf友情提供)
< filename,重定向标准输入自文件
举个例子,在用find的时候,有的目录不允许访问,find就输出很多行的错误,真正的搜索结果就看不到了。这时我会把标准错误重定向到空设备去。
1. find / -name "filename" 2> /dev/null
再比如在用gdb进行自动测试的时候,把命令写到一个文件里,然后送入gdb。
1. gdb program < test_script.gdb
管道
管道的原理上面基本介绍清楚了。管道是让用户将不同程序间的标准输入、标准输出连接起来,而不单单是重定向到文件。用法是在命令间用“|”连接起来。
app1 | app2
我最常用的几个情况:
1. 程序输出太多,用less慢慢看。
1. verbose_app | less
2. 在程序输出里面进行搜索。一种方法可以送到less里面在用less搜索。这里用另外一个命令,grep。
verbose_app | grep pattern
# pattern是被搜索的内容。如果有空格,用双引号括起来。如果想使用扩展正则表达式,用grep -E。
3. 因为在重定向了以后,被重定向的管道就不再打印到屏幕了。如果又想打印到文件,又想打印到屏幕,可以用tee命令
verbose_app | tee filename | another_app
xargs
如果后面的程序必须要命令行参数,而不接受管道传参数,就要使用xargs。
1. 先演示一下原理。
echo "arg1 arg2" | xargs app
# 相当于
app arg1 arg2
2. 用find或者ls查找文件,然后将所有文件tar了。
find . -type f | xargs tar -cvzf output.tar.gz
3. 计算源文件行数。这里要用到一个叫wc的命令,是用来计算文件单词数、字符数和行数的。如果管道到wc的话,wc会将数据当做文本来进行计算。文件名只有从命令行传递
find . −name"∗.c"−o−name"∗.h"−o−name"∗.cpp"−o−name"∗.hpp"−name"∗.c"−o−name"∗.h"−o−name"∗.cpp"−o−name"∗.hpp" -type f | xargs wc -l
# 或者
find . -type f | grep -E "\.[ch](pp)?$" | xargs wc -l
重定向的>,2>,<之类的原理是把标准输入等用新的管道来取代。
我一开始是这样写的
command >/dev/null 2>&1
这样写的问题是,>已经将标准输出用null设备替换了,然后2>&1将标准错误接到“标准输出”上,而“标准输出”现在已经变成了null设备,也就是说标准错误接到了null设备上。
正确的方法是
command 2>&1 >/dev/null
另外,交换标准输出和标准错误:
command 3>&1 1>&2 2>&3
xargs可以解决这种问题,xargs可以读入stdin的数据,并且以空格或断行符进行分辨,将stdin的数据分隔成某个命令的参数。xargs可以将单行或多行文本输入转换成其他格式。
xargs可以将stdin中以空格或换行符进行分隔的数据,形成以空格分隔的参数(arguments),传递给其他命令。因为以空格作为分隔符,所以有一些文件名或者其他意义的名词内含有空格的时候,xargs可能会误判。简单来说,xargs是给其他命令传递参数的一个过滤器,是构建单行命令的重要组件之一。
之所以要用到xargs,是因为由于很多命令不支持使用管道|来传递参数,例如:
1
2
|
find /sbin -perm +700 |ls -l //这个命令是错误,因为标准输入不能作为ls的参数 find /sbin -perm +700 |xargs ls -l //这样才是正确的 |
参数: -0: 如果输入的stdin含有特殊字符,例如`, \, 空格键等字符时,这个参数可以将它还原成一般字符。这个参数可以用于特殊状态。
-e:这个是EOF(end of file)的意思。后面可以接一个字符串,当xargs分析到这个字符串时,就会停止工作。
-p:在执行每个命令的参数时,都会询问用户。
-n:后面接次数,每次command命令执行时,要使用几个参数。
-d:使用自己的定义的定界符来分隔参数。
-I:大写i,将xargs的每项名称,一般是一行一行赋值给{},可以{}代替。使用-i的时候,命令以循环的方式执行。如果有3个参数,
那么命令就会连同{}一起被执行3次。在每一次执行中{}都会被替换为相应的参数。
-0:如果输入的stdin含有特殊字符,例如反引号`、反斜杠\、空格等字符时,xargs可以将它还原成一般字符。为xargs的默认选项。
-e <flag>,-E <flag>,
--eof=<eof-str>:eof是end of file string的意思。flag可以是一个字符串或者是由空格分隔的多个字符串,当xargs分析到这个flag时,就会停止工作。见示例2。
-p:当每次执行一个argument的时候询问一次用户。
-n <num>:表示命令在执行的时候一次使用的argument的个数,由num指定,默认是用所有的参数。
-t:表示先打印命令,然后再执行。
-a <file>:从文件中读入作为sdtin。
-i,-I:其中-I某些Linux版本不支持。将xargs的输出每一项参数,单独赋值给后面的命令,参数需要用{}代替。见示例3。
-r:或者
--no-run-if-empty,当xargs的输入为空的时候则停止xargs,不用再去执行后面的命令了,-r是xargs的默认选项。
-s <num>:命令行的最大字符数,指的是xargs后面那个命令的最大命令行字符数,包括命令、空格和换行符。每个参数单独传入xargs后面的命令。见示例4。
-L <line_num>:设置标准输入中最大的行数作为命令每一次执行的参数。见示例5。
-d <delim>,
--delimiter=<delim>: xargs处理标准输入默认是按换行符和空格作为分隔符,输出arguments的分隔符是空格,这里修改xargs处理标准输入时的分隔符。
-x:eXit的意思,主要是配合-s使用,当命令行字符数大于-s指定的数值时,退出xargs。
-P:修改最大的进程数,默认是1,为0时候为
as
many
as
it can。该选项比较少用,目前还不清楚该用法。</delim></delim></line_num></num></file></num></eof-str></flag></flag>
范例:
例1:使用-0选项删除test文件夹中文件名含空格的文件"file 1.log" "file 2.log"
- [root@centos6 test]# touch "file 1.log" "file 2.log"
- [root@centos6 test]# ls -l *.log
- -rw-r--r--. 1 root root 0 Jun 16 18:57 file 1.log
- -rw-r--r--. 1 root root 0 Jun 16 18:57 file 2.log
- [root@centos6 test]# find -name '*.log' | xargs rm #直接删除不成功,xargs默认是以空白字符(空格、TAB、换行符)
- 来分割记录
- rm: cannot remove `./file': No such file or directory
- rm: cannot remove `2.log': No such file or directory
- rm: cannot remove `./file': No such file or directory
- rm: cannot remove `1.log': No such file or directory
- [root@centos6 test]# find -name '*.log' -print0 | xargs -0 rm # find在打印出一个文件名之后接着输出一个NULL字符,
- 然后告诉xargs用NULL字符来作为记录的分隔
- [root@centos6 test]# find -name '*.log'
例2:使用-e选项只打印”a bc d e rf f"中字符e之前的字符串
- [root@centos6 test]# echo a bc d e rf f | xargs -ee
- a bc d
例3:使用-p选项
- [root@centos6 test]# ls a* | xargs -p rm # 执行rm前,先询问下
- rm a1 a2 a3 ?...y
- [root@centos6 test]# ls a*
- ls: cannot access a*: No such file or directory
例4:使用-n选项批量创建user1,user2,user3三个用户
- [root@centos6 test]# echo user1 user2 user3 | xargs -n 1 useradd
- [root@centos6 test]# cat /etc/passwd | tail -3
- user1:x:708:726::/home/user1:/bin/bach
- user2:x:709:727::/home/user2:/bin/bach
- user3:x:710:728::/home/user3:/bin/bach
(3)将当前目录的所有文件添加后缀名。
1
|
ls | xargs -t -i mv {} {}.bak |
(4)设置命令行的最大字符数。参数默认一个一个单独传入命令中执行。
1
2
3
4
5
|
[b3335@MIC test]$ echo "01234 56789" |xargs -t -s 11 echo 01234 01234 echo 56789 56789 |
(5)设置标准输入中每次多少行作为命令的参数,默认是将标准输入中所有行的归并到一行一次性传给命令执行。
1
2
3
4
5
|
[b3335@MIC test]$ echo -e "01234\n56789\n01234" | xargs -t -L 2 echo echo 01234 56789 01234 56789 echo 01234 01234 |
例6:将单行输入转换成多行输出
- [root@centos6 test]# cat example.txt | xargs -n 3
- 1 2 3
- 4 5 6
- 7 8 9
- 10 11 12
例7:使用-d选项分隔字符串成单行或多行
- [root@centos6 test]# echo "splitXsplitXsplitXsplit" | xargs -d X
- split split split split
- [root@centos6 test]# echo "splitXsplitXsplitXsplit" | xargs -d X -n 2 # 结合-n选项使用
- split split
- split split
例8:使用-I(大写i)
- [root@centos6 xargsi]# echo This is file1.txt > file1.txt
- [root@centos6 xargsi]# echo This is file2.txt > file2.txt
- [root@centos6 xargsi]# echo This is file3.txt > file3.txt
- [root@centos6 xargsi]# vim files.txt
- [root@centos6 xargsi]# cat files.txt
- file1.txt
- file2.txt
- file3.txt
- [root@centos6 xargsi]# cat files.txt | xargs -I {} cat {} 等价于cat files.txt | ( while read arg ; do cat $arg; done )
- This is file1.txt
- This is file2.txt