曲径通幽论坛

 找回密码
 立即注册
搜索
查看: 5176|回复: 0
打印 上一主题 下一主题

xargs 为指令产生参数

[复制链接]

4918

主题

5880

帖子

3万

积分

GROAD

曲径通幽,安觅芳踪。

Rank: 6Rank: 6

积分
34397
跳转到指定楼层
楼主
发表于 2009-1-3 23:19:38 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
在使用 find 命令的 -exec 选项处理匹配到的文件时,find 命令将所有匹配到的文件一起传递给 exec 执行。不幸的是,有些系统对能够传递给 exec 的命令长度有限制,这样在 find 命令运行几分钟之后,就会出现溢出错误。错误信息通常是"参数列太长"或"参数列溢出"。这就是xargs 命令的用处所在,特别是与 find 命令一起使用。find 命令把匹配到的文件传递给 xargs 命令,而 xargs 命令每次只获取一部分文件而不是全部,不像 -exec 选项那样。这样它可以先处理最先获取的一部分文件,然后是下一批,并如此继续下去。在有些系统中,使用 -exec选项会为处理每一个匹配到的文件而发起一个相应的进程,并非将匹配到的文件全部作为参数一次执行;这样在有些情况下就会出现进程过多,系统性能下降的问题,因而效率不高;而使用 xargs 命令则只有一个进程。另外,在使用 xargs 命令时,究竟是一次获取所有的参数,还是分批取得参数,以及每一次获取参数的数目都会根据该命令的选项及系统内核中相应的可调参数来确定。  

xargs 可以将多行的输入变为单行的输出
测试文本内容:
cat temp.txt
welcome
to
groad
使用 xargs 命令将上面的多行输入变为一行:
cat temp.txt |xargs
welcome to groad
这其中的道理也就是这些输入都要作为命令的参数,而命令行参数一般都是在一行上的。

通过 -n 参数可以实现单行输入转变为多行输出
测试文本内容:
# cat temp.txt
1 2 3 4 5 6 7 8 9 10 11 12 13
转变为多行输出:
# cat temp.txt |xargs -n 3
1 2 3
4 5 6
7 8 9
10 11 12
13
-n 选项指定每一条命令行上最多的参数个数。
上面的参数分隔默认是以空格(" ") 作为分隔符的。但我们也可以通过 -d 选项来指定别的分隔符,比如一个测试文本如下
# cat temp.txt
welcome~to~www~groad~net
使用 -d 参数指定分隔符:
# cat temp.txt |xargs -d '~'
welcome to www groad net
使用 -d 选项指定文本分隔符实际上是改变了 IFS环境变量的值。

当然,可以将 -d 和上面的 -n 选项一块使用,如:
# cat temp.txt |xargs -d '~' -n 2
welcome to
www groad
net

使用 -I 选项进行替代

先假设有这么一个脚本 mysc.sh,它要运行时需要输入相应的参数,如:
./mysc.sh -s yourarg -p
在上面的命令中,-s 和 -p 假设是固定不变的选项参数,而 yourarg 是可变的参数;再假设这个参数来自一个 myarg.txt 文件,且该文件中存储有多个不同的 yourarg 参数,在这种情况下,我们可以如下从 myarg.txt 中获得参数并依次传递到 mysc.sh -s yourarg -p 这条命令中:
$ cat myarg.txt | xargs -I {} ./mysc.sh -s {} -p


让我们来看看 xargs 命令是如何同find命令一起使用的,并给出一些例子。


下面的例子在整个系统中查找内存信息转储文件(core dump) ,然后把结果保存到 /tmp/core.log 文件中:
$ find . -name "core" -print | xargs echo "" >/tmp/core.log

下面的例子在/apps/audit目录下查找所有用户具有读、写和执行权限的文件,并收回相应的写权限:
$ find /apps/audit -perm -7 -print | xargs chmod o-w

在下面的例子中,我们用 grep 命令在所有的普通文件中搜索 device 这个词:
[quote]$ find / -type f -print | xargs grep "device"

在下面的例子中,我们用 grep 命令在当前目录下的所有普通文件中搜索 DBO 这个词:

$ find . -name \* -type f -print | xargs grep "DBO"
注意,在上面的例子中, \ 用来取消 find 命令中的 * 在shell中的特殊含义。

在查找文件的过程中,会出现一种文件名中含有空格的文件,比如“hello groad.txt”,这时如果按照下面的方式传递到 xargs ,那么会发生不希望的结果:
# ls -l
total 0
-rw-r--r-- 1 root root 0 2012-03-23 13:59 groad.txt
-rw-r--r-- 1 root root 0 2012-03-23 13:59 hello groad.txt

# find . -type f -name "*.txt" -print | xargs rm -f

# ls -l
total 0
-rw-r--r-- 1 root root 0 2012-03-23 13:59 hello groad.txt
由上面可以看到,并不能删除 "hello groad.txt" 这个文件,因为它含有空格,因为默认情况下 xargs 并不能分辨出来自 find 的输出中的分隔符(可能是 '\n' ,也可能是 ' '),这样就会导致 xargs 的解析错误。然而 find 命令里的 -print0 选项会使输出的全文件名结尾包含一个 '\0' (而不是 -print 选项所用的换行('\n'))。这样,在 xargs 里再用一个 -0 选项以表明它所接收的输入正是要以 '\0' 结尾的。因此这两者一配合,就能够删除掉含有空格的文件名了,如:
# find . -name "*.txt" -print0 |xargs -0 rm -f

小结

find命令是一个非常优秀的工具,它可以按照用户指定的准则来匹配文件。使用 exec 和 xargs 可以使用户对所匹配到的文件执行几乎所有的命令。
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|曲径通幽 ( 琼ICP备11001422号-1|公安备案:46900502000207 )

GMT+8, 2025-6-18 07:29 , Processed in 0.081385 second(s), 22 queries .

Powered by Discuz! X3.2

© 2001-2013 Comsenz Inc.

快速回复 返回顶部 返回列表