如何为每个给定的输入行使xargs执行一次命令? 它的默认行为是将行块化并执行一次命令,将多行传递给每个实例。
来自http://en.wikipedia.org/wiki/Xargs:
find / path -type f -print0 | xargs -0 rm
在此示例中,查找使用长文件名列表输入xargs。然后xargs将此列表拆分为子列表,并为每个子列表调用rm一次。这比功能相同的版本更有效:
find / path -type f -exec rm'{}'\;
我知道find有“exec”标志。我只是引用另一个资源的说明性示例。
答案 0 :(得分:356)
以下内容仅在输入中没有空格时才有效:
xargs -L 1
xargs --max-lines=1 # synonym for the -L option
从手册页:
-L max-lines
Use at most max-lines nonblank input lines per command line.
Trailing blanks cause an input line to be logically continued on
the next input line. Implies -x.
答案 1 :(得分:162)
在我看来,此页面上的所有现有答案都是错误的,包括标记为正确的答案。这源于这个问题含糊不清的事实。
摘要:如果要为给定的每一行输入执行一次命令,“将整行(不带换行符)传递给命令一个单个参数,然后这是与UNIX兼容的最佳方法:
... | tr '\n' '\0' | xargs -0 -n1 ...
GNU xargs
可能有也可能没有允许您取消tr
的有用扩展,但它们在OS X和其他UNIX系统上不可用。
现在有很长的解释......
使用xargs时需要考虑两个问题:
为了测试xargs的行为,我们需要一个实用程序来显示它被执行的次数以及有多少个参数。我不知道是否有标准实用程序可以做到这一点,但我们可以在bash中轻松编写代码:
#!/bin/bash
echo -n "-> "; for a in "$@"; do echo -n "\"$a\" "; done; echo
假设您将其保存为当前目录中的show
并使其可执行,以下是它的工作原理:
$ ./show one two 'three and four'
-> "one" "two" "three and four"
现在,如果原来的问题确实是关于上面的第2点(正如我认为的那样,在阅读了几次之后)并且应该像这样阅读(粗体更改):
如何让xargs为每个输入的参数执行一次命令?它的默认行为是将输入插入参数并执行命令尽可能少,将多个参数传递给每个实例。
然后答案是-n 1
。
让我们比较xargs的默认行为,它将输入分成空格并尽可能少地调用命令:
$ echo one two 'three and four' | xargs ./show
-> "one" "two" "three" "and" "four"
及其对-n 1
的行为:
$ echo one two 'three and four' | xargs -n 1 ./show
-> "one"
-> "two"
-> "three"
-> "and"
-> "four"
另一方面,如果最初的问题是关于第1点的输入拆分而且它应该像这样阅读(很多人来到这里似乎认为是这种情况,或者混淆了这两个问题):
然后答案更加微妙。如何让xargs为每一行输入执行命令完全一个参数?它的默认行为是将行空白。
有人会认为-L 1
可能会有所帮助,但事实证明它并没有改变参数解析。它只对每个输入行执行一次命令,其参数与该输入行的参数一样多:
$ echo $'one\ntwo\nthree and four' | xargs -L 1 ./show
-> "one"
-> "two"
-> "three" "and" "four"
不仅如此,如果一行以空格结尾,则会附加到下一行:
$ echo $'one \ntwo\nthree and four' | xargs -L 1 ./show
-> "one" "two"
-> "three" "and" "four"
显然,-L
并不是要改变xargs将输入拆分为参数的方式。
以跨平台方式(不包括GNU扩展)这样做的唯一参数是-0
,它将输入分成NUL字节。
然后,只需要在tr
的帮助下将换行符翻译成NUL:
$ echo $'one \ntwo\nthree and four' | tr '\n' '\0' | xargs -0 ./show
-> "one " "two" "three and four"
现在,参数解析看起来很好,包括尾随空格。
最后,如果将此技术与-n 1
结合使用,每个输入行只能执行一个命令,无论您输入什么,这可能是查看原始问题的另一种方式(可能是最直观的,鉴于标题):
$ echo $'one \ntwo\nthree and four' | tr '\n' '\0' | xargs -0 -n1 ./show
-> "one "
-> "two"
-> "three and four"
答案 2 :(得分:22)
如果要运行来自find
的每个行(即结果)的命令,那么您需要xargs
为什么?
尝试:
find
路径 -type f -exec
你的命令 {} \;
其中文字{}
被文件名替换,\;
需要文字find
才能知道自定义命令在那里结束。
(在您的问题编辑后,澄清您了解-exec
)
来自man xargs
:
-L max-lines
每个命令行最多使用 max-lines 非空白输入行。尾随 空白导致输入行在下一个输入行上逻辑上继续。 意味着-x。
请注意,如果您使用xargs
,以空格结尾的文件名会导致您遇到麻烦:
$ mkdir /tmp/bax; cd /tmp/bax
$ touch a\ b c\ c
$ find . -type f -print | xargs -L1 wc -l
0 ./c
0 ./c
0 total
0 ./b
wc: ./a: No such file or directory
因此,如果您不关心-exec
选项,最好使用-print0
和-0
:
$ find . -type f -print0 | xargs -0L1 wc -l
0 ./c
0 ./c
0 ./b
0 ./a
答案 3 :(得分:14)
如何让xargs对给定的每一行输入执行一次命令?
我没有使用-L 1
答案,因为它不处理包含空格的文件,这是find -print0
的关键功能。
echo "file with space.txt" | xargs -L 1 ls
ls: file: No such file or directory
ls: space.txt: No such file or directory
ls: with: No such file or directory
更好的解决方案是使用tr
将换行符转换为null(\0
)个字符,然后使用xargs -0
参数。
echo "file with space.txt" | tr '\n' '\0' | xargs -0 ls
file with space.txt
如果您需要限制调用次数,可以使用-n 1
参数为每个输入调用一次程序:
echo "file with space.txt" | tr '\n' '\0' | xargs -0 -n 1 ls
这也允许您在将中断转换为空值之前过滤find 的输出。
find . -name \*.xml | grep -v /workspace/ | tr '\n' '\0' | xargs -0 tar -cf xml.tar
答案 4 :(得分:10)
另一种选择......
find /path -type f | while read ln; do echo "processing $ln"; done
答案 5 :(得分:4)
find path -type f | xargs -L1 command
就是你所需要的一切。
答案 6 :(得分:4)
这两种方式也有效,并且适用于其他未使用find的命令!
xargs -I '{}' rm '{}'
xargs -i rm '{}'
示例用例:
find . -name "*.pyc" | xargs -i rm '{}
即使pyc文件包含空格,也会删除此目录下的所有pyc文件。
答案 7 :(得分:3)
以下命令将在/path
中找到所有文件(-type f),然后使用cp
将它们复制到当前文件夹。请注意,-I %
用于在cp
命令行中指定占位符字符,以便可以在文件名后面放置参数。
find /path -type f -print0 | xargs -0 -I % cp % .
使用xargs(GNU findutils)4.4.0进行测试
答案 8 :(得分:1)
您可以分别使用--max-lines或--max-args标志限制行数或参数(如果每个参数之间有空格)。
-L max-lines Use at most max-lines nonblank input lines per command line. Trailing blanks cause an input line to be logically continued on the next input line. Implies -x. --max-lines[=max-lines], -l[max-lines] Synonym for the -L option. Unlike -L, the max-lines argument is optional. If max-args is not specified, it defaults to one. The -l option is deprecated since the POSIX standard specifies -L instead. --max-args=max-args, -n max-args Use at most max-args arguments per command line. Fewer than max-args arguments will be used if the size (see the -s option) is exceeded, unless the -x option is given, in which case xargs will exit.
答案 9 :(得分:0)
我似乎没有足够的声誉向Tobia's answer above添加评论,所以我添加了这个“答案”,以帮助我们这些想要以同样的方式试验xargs
的人Windows平台。
这是一个Windows批处理文件,与Tobia的快速编码“show”脚本完全相同:
@echo off
REM
REM cool trick of using "set" to echo without new line
REM (from: http://www.psteiner.com/2012/05/windows-batch-echo-without-new-line.html)
REM
if "%~1" == "" (
exit /b
)
<nul set /p=Args: "%~1"
shift
:start
if not "%~1" == "" (
<nul set /p=, "%~1"
shift
goto start
)
echo.
答案 10 :(得分:0)
@Draemon的答案似乎与“ -0”正确,即使文件中有空格。
我正在尝试xargs命令,但发现“ -0”与“ -L”完美配合。即使空格也被处理(如果输入为null终止)。以下是一个示例:
#touch "file with space"
#touch "file1"
#touch "file2"
以下将拆分null并在列表中的每个参数上执行命令:
#find . -name 'file*' -print0 | xargs -0 -L1
./file with space
./file1
./file2
因此,-L1
如果与“ -0”一起使用,将对每个以null结尾的字符执行自变量。要查看差异,请尝试:
#find . -name 'file*' -print0 | xargs -0 | xargs -L1
./file with space ./file1 ./file2
这将执行一次:
#find . -name 'file*' -print0 | xargs -0 | xargs -0 -L1
./file with space ./file1 ./file2
该命令将执行一次,因为“ -L”现在不会在空字节上分割。您需要同时提供“ -0”和“ -L”才能正常工作。
答案 11 :(得分:-2)
在您的示例中,将find的输出管道输出到xargs的点是find的-exec选项的标准行为是为每个找到的文件执行一次命令。如果你正在使用find,并且你想要它的标准行为,那么答案很简单 - 不要使用xargs开头。
答案 12 :(得分:-3)
在当前或子文件夹的每个build.xml上执行ant task clean-all。
find . -name 'build.xml' -exec ant -f {} clean-all \;