代码改变世界

xargs exec

2018-11-07 10:57  xin37521  阅读(265)  评论(0)    收藏  举报

ls | xargs -t -I {} mv {} {}.old

技巧: find -print0  与 xargs -0 的结合避免文件名有特殊字符如空格,引号等无法处理:

 #find . -name "*.txt" print0 |xargs -0 rm {} \

#echo user1 user2 user3 | xargs -n 1 useradd
# find -name '*.log' -print0 | xargs -0 rm # find在打印出一个文件名之后接着输出一个NULL字符,
然后告诉xargs用NULL字符来作为记录的分隔

find . -name "*.jar" -type f -exec unzip -l {} /;        unzip不支持多参数  所以不能用xargs

用法: xargs [-0epnd] command

       参数:

                  -0: 如果输入的stdin含有特殊字符,例如`, \, 空格键等字符时,这个参数可以将它还原成一般字符。这个参数可以用于特殊状态。

                  -e:这个是EOF(end of file)的意思。后面可以接一个字符串,当xargs分析到这个字符串时,就会停止工作。

                  -p:在执行每个命令的参数时,都会询问用户。

                  -n:后面接次数,每次command命令执行时,要使用几个参数。

                  -d:使用自己的定义的定界符来分隔参数。

                   -I:大写i,将xargs的每项名称,一般是一行一行赋值给{},可以{}代替。使用-i的时候,命令以循环的方式执行。如果有3个参数,

                          那么命令就会连同{}一起被执行3次。在每一次执行中{}都会被替换为相应的参数。

 

ls | xargs -d"o" -n 2 -t
ls | xargs -d"o" -p
ls | xargs -i echo {}


---------------------

xargs

  find将所有匹配到的文件通过管道,一股脑全部传递,这些文件名组合成命令的参数。

exec

  find将匹配到的文件传给exec执行,每找到一次传一次。

  但是,如果文件名太过长(超过了几K)时,会出现命令行超长报错的问题。

 

 

参考 https://www.cnblogs.com/f-ck-need-u/p/5925923.html

 

对find,xargs,grep和管道的一些深入理解

 

转自于:http://fatmouse.xyz/2016/05/10/2016-05-10-find-grep-xargs-and-pipe/

 

问题

相信大家都知道在目录中搜索含有固定字符串文件的命令:

1
find . -name '*.py' |xargs grep test

 

刚开始的时候,我不熟悉xargs命令,所以直接使用的命令是

1
find . -name '*.py' |grep test

 

结果并不是自己所期望的。此命令只是找出文件名*.txttest的情况。

这里我就研究一下,究竟xargs做了什么,使得结果不相同。

参数与标准输入

这两个词我们在Linux命令中是很常见的。但是参数和标准输入其实是有区别的。我们日常使用的很多命令,例如ls -lah .中。l, a, h ,.都是命令ls的参数。至于标准输入,可以说它某种流数据。而通常来讲标准输入的流数据来源就是我们的终端输入。在Linux命令中,有些命令可以接收标准输入,有些是不能的。像上面的ls,就是只能接收参数,不能接收标准输入。像cat命令或echo命令,这些是可以的。

怎么分辨一个命令可不可以接收标准输入?很简单,当你敲完命令回车后,终端会等待接收你的输入,例如当你在终端输入cat后,终端会等待你输入字符,当你输入一些字符后,然后按Ctrl-C发送终止符号。这时cat命令接收标准输入完毕,执行命令,也就是将刚才键入的内容输出的标准输出上(屏幕)。

管道

管道的作用是将前面命令的标准输出作为后面命令的标准输入。这里要注意,后面的命令接收的是标准输入,所以如果命令不支持接收标准输入,那么就不能直接使用管道,例如常用的ls命令,只能使用参数,而不能使用标准输入,所以[command] | ls是不能使用的。而命令如echocat就可以。那么肯定有方法来实现这些不能使用标准输入的命令与管道结合,这时候xargs便出场了。

xargs命令

xargs命令通俗来讲就是将标准输入转成各种格式化的参数,所以命令[command 1] | xargs [command 2]就是将command 1的标准输出结果,通过管道|变成xargs的标准输入,然后xargs再将此标准输入变成参数,传给[command 2]。这样一来,通过xargs命令,我们便可以在管道后面使用那些不接收标准输入的命令了。例如[command 1]|xargs ls,是不是很熟悉?

find与grep

有了以上的知识点,到这里终于可以解答最开始的问题了。为什么命令

1
find . -name '*.py' |grep test

 

1
find . -name '*.py' |xargs grep test

 

的结果是不一样的了。

我们首先来查看grep手册。通过man grep命令。

1
2
DESCRIPTION
grep searches the named input FILEs (or standard input if no files are named, or if a single hyphen-minus (-) is given as file name) for lines containing a match to the given PATTERN. By default, grep prints the matching lines.

 

这里可以看到grep是支持标准输入的。

假设目录存在如下文件:

1
2
$ ls
Altitest.py python.py runora.py test.py TransferFile.py

 

那么对于第一个命令find . -name '*.py' |grep test,是将前面命令的标准输出作为标准输入传给了grep test,那么grep是从这些标准输入寻找test字符,也就是文件名组成的字符流

1
2
3
$ find . -name '*.py' |grep test
./Altitest.py
./test.py

 

可以看到最终选择出的是这些文件名。

而对于第二个命令find . -name '*.py' |xargs grep test,通过xargsfind得到的文件名成为了参数传给后面的grep,那么这时候这些文件名就是实实在在的文件标识,grep接收后会按正常的使用方式在各文件中搜寻字符串。

1
2
3
4
5
6
7
#find . -name '*.py' |xargs grep test
./runora.py:testConn = cx_Oracle.connect('user/passwd@tns')
./runora.py:testCursor = testConn.cursor()
./runora.py:testCursor.execute("select * from table")
./runora.py:rows = testCursor.fetchall()
./runora.py:testCursor.close()
./runora.py:testConn.close()

 

到这里算是将findgrepxargs和管道的作用理解清楚了。

  1. xargs还有指定参数位置的作用。假设我们要将目录下所有的.py文件放到Python目录中去,可以使用命令
    find . -name '*.py' | xargs -I {} mv {} ./Python
    参数-I指定了管道前命令作为参数所应该在管道后面命令的位置。

  2. 我们在查看很多命令手册时,手册会说明命令的使用方法。例如
    grep [OPTIONS] PATTERN [FILE...],也就是命令的最后一个位置是文件名[FILE]
    这里要注意这个文件名[FILE]也是参数