如何在 xargs 命令中使用 > ?

我希望找到一个 bash 命令,它允许我对目录中的每个文件进行 grep,并将该 grep 的输出写入一个单独的文件。我猜是做了这种事

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

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

有人知道怎么用 xargs 吗?我只是用这个 grep 场景作为例子来说明我的 xargs 问题,因此任何不使用 xargs 的解决方案都不适用于我。

71252 次浏览

没有 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添加注释后的单引号。

不要犯这样的错误:

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

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

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

适用于 xargsfind

顺便说一下,不要在没有 -0选项的情况下使用 xargs (除非是非常罕见且可控的一次性交互使用,因为您并不担心会破坏数据)。

也不要解析 ls。永远不要。使用 globbing 或者 find代替: 译自: 美国《 http://mywiki.wooledge.org/parsingls 》杂志网站(http://mywiki.woledge.org/parsingLs)

对于需要递归的内容使用 find,对于其他内容使用带有 globb 的简单循环:

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

或非递归的:

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

注意引号的正确使用。

我假设您的例子只是一个例子,您可能需要 > 用于其他事情。GNU 并行 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 883c667e01eed62f975ad28b6d50e22a
12345678 883c667e 01eed62f 975ad28b 6d50e22a
$ md5sum install.sh | grep cc21b4c943fd03e93ae1ae49e28573c0
cc21b4c9 43fd03e9 3ae1ae49 e28573c0
$ sha512sum install.sh | grep da012ec113b49a54e705f86d51e784ebced224fdf
79945d9d 250b42a4 2067bb00 99da012e c113b49a 54e705f8 6d51e784 ebced224
fdff3f52 ca588d64 e75f6033 61bd543f d631f592 2f87ceb2 ab034149 6df84a35
$ bash install.sh

如果需要将它移动到没有安装 GNU 并行的服务器,请尝试 parallel --embed

实际上,这里的大多数答案并不适用于所有文件名(如果它们包含双引号和单引号) ,包括 lhunath 和 Stephan202的答案。

这个解决方案使用单引号和双引号的文件名:

find . -mindepth 1 -print0 | xargs -0 -I{} sh -c 'grep ABC "$1" > "$1.out"' -- {}

下面是一个同时使用单引号和双引号的文件名测试:

echo ABC > "I'm here.txt"


# lhunath solution (hangs waiting for input)


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


# Stephan202 solutions


$ find . -mindepth 1 -maxdepth 1 -type f -exec sh -c "grep ABC '{}' > '{}.out'" \;
grep: ./Im: No such file or directory
grep: here.txt > ./Im here.txt.out: No such file or directory


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


# this solution
$ find . -mindepth 1 -print0 | xargs -0 -I{} sh -c 'grep ABC "$1" > "$1.out"' -- {}


$ ls -1
"I'm here.txt"
"I'm here.txt.out"