如何在xargs命令中使用>?


160

我想找到一个bash命令,它将使我grep目录中的每个文件并将该grep的输出写入单独的文件。我的猜测是要做这样的事情

ls -1 | xargs -I{} "grep ABC '{}' > '{}'.out"

但是据我所知,xargs不喜欢双引号。但是,如果删除双引号,那么该命令会将整个命令的输出重定向到一个名为'{}'。out的文件中,而不是一系列单独的文件中。

有人知道使用xargs做到这一点的方法吗?我只是以这个grep场景为例来说明xargs的问题,因此任何不使用xargs的解决方案都不适合我。

Answers:


201

请勿犯以下错误:

sh -c "grep ABC {} > {}.out"

这会在很多情况下中断,包括时髦的文件名,不可能正确引用。您{}必须始终对该命令使用一个完全独立的参数,以避免代码注入错误。您需要做的是:

xargs -I{} sh -c 'grep ABC "$1" > "$1.out"' -- {}

适用于xargsfind

顺便说一句,切勿在没有该-0选项的情况下使用xargs (除非用于非常罕见且受控制的一次性交互使用,而您不必担心会破坏数据)。

也不要解析ls。曾经 使用通配符或find代替:http://mywiki.wooledge.org/ParsingLs

使用find的需要递归和一个简单的循环与一切一水珠的一切:

find /foo -exec sh -c 'grep "$1" > "$1.out"' -- {} \;

或非递归:

for file in *; do grep "$file" > "$file.out"; done

注意正确使用引号。


提出支持,但值得怀疑。不使用xargs-0:这仅适用于当你管find的与输出xargs,对不对?当我做xargs -a <input_file>什么时,我将如何使用它?大多数命令都喜欢grep使用with \n和not 这样的输出,\0.我能想到的解决此问题的唯一方法是tr再次使用它来修复该问题。但是为什么仅将它与一起使用很重要-0
legends2k 2014年

3
@ legends2k,因为当您不使用时-0xargs将使用您的文件名并破坏其中的所有空格,引号和反斜杠。您应该只是忘了把它xargs当作工具。如果您有行,请使用bash循环来迭代这些行: while read line; do <command> "$REPLY"; done < file-with-linescommand | while ...
lhunath 2014年

1
哇,不知道,谢谢你的细节!因此,对于可移植性(因为并非所有xargs都是GNU的),xargs除非可以与一起使用,否则需要避免-0。谢谢。
legends2k 2014年

1
尽管我欣赏此特定用例的详细说明,但问题在于重定向的输出xargs,但并不总是涉及解析ls或使用sh -c。这丝毫没有回答问题,但是该问题的第一个Google搜索结果,只会增加混乱。
pandasauce

1
@Ihunath,您好,您的回答对我来说效果很好。但是,您可以提供一些详细的解释或链接xargs -I{} sh -c 'grep ABC "$1" > "$1.out"' -- {}吗?特别是,嵌入的规则(双引号)和末尾的“-”符号。谢谢
Scott Yang

40

没有xargs以下情况的解决方案:

find . -mindepth 1 -maxdepth 1 -type f -exec sh -c "grep ABC '{}' > '{}.out'" \;

......而同样的做法可以 xargs,事实证明:

ls -1 | xargs -I {} sh -c "grep ABC '{}' > '{}.out'"

编辑:由lhunath备注后添加单引号。


他说他想使用xargs。我也发布了一个没有它的解决方案,但是一旦看到他需要xargs便将其删除。
Zifre

你是对的。我发布答案的原因是,拥有替代解决方案来完成这项工作总比没有解决方案要好。事实证明,它使我走上了正确的道路,以找到所需的答案(即sh -c技巧)。
09年

14

我假设您的示例只是一个示例,您可能需要>做其他事情。GNU Parallel http://www.gnu.org/software/parallel/可能会帮助您。只要您的文件名不包含\ n,它就不需要附加的引号:

ls | parallel "grep ABC {} > {}.out"

如果文件名中带有\ n:

find . -print0 | parallel -0 "grep ABC {} > {}.out"

另外,您还可以并行运行作业。

观看介绍性视频以了解更多信息:http : //pi.dk/1

10秒的安装将尝试进行完整安装;如果失败,则进行个人安装;如果失败,则进行最小安装:

$ (wget -O - pi.dk/3 || lynx -source pi.dk/3 || curl pi.dk/3/ || \
   fetch -o - http://pi.dk/3 ) > install.sh
$ sha1sum install.sh | grep 3374ec53bacb199b245af2dda86df6c9
12345678 3374ec53 bacb199b 245af2dd a86df6c9
$ md5sum install.sh | grep 029a9ac06e8b5bc6052eac57b2c3c9ca
029a9ac0 6e8b5bc6 052eac57 b2c3c9ca
$ sha512sum install.sh | grep f517006d9897747bed8a4694b1acba1b
40f53af6 9e20dae5 713ba06c f517006d 9897747b ed8a4694 b1acba1b 1464beb4
60055629 3f2356f3 3e9c4e3c 76e3f3af a9db4b32 bd33322b 975696fc e6b23cfb
$ bash install.sh

如果需要将其移动到未安装GNU Parallel的服务器上,请尝试parallel --embed

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.