题
我想找到一个 bash 命令,它可以让我 grep 目录中的每个文件,并将该 grep 的输出写入一个单独的文件。我的猜测是做这样的事情
ls -1 | xargs -I{} "grep ABC '{}' > '{}'.out"
但是,据我所知, xargs 不喜欢双引号。但是,如果我删除双引号,则该命令会将整个命令的输出重定向到名为 '{}'.out 的单个文件,而不是一系列单独的文件。
有谁知道使用 xargs 执行此操作的方法吗?我只是使用这个 grep 场景作为示例来说明我的 xargs 问题,因此任何不使用 xargs 的解决方案都不适合我。
解决方案
不要犯这样的错误:
sh -c "grep ABC {} > {}.out"
这在很多情况下都会崩溃,包括时髦的文件名,并且不可能正确引用。你的 {}
必须始终是命令的一个完全独立的参数,以避免代码注入错误。你需要做的是:
xargs -I{} sh -c 'grep ABC "$1" > "$1.out"' -- {}
适用于 xargs
也 find
.
顺便说一句,如果没有 -0
选项(除非是非常罕见且受控的一次性交互使用,您不担心会破坏数据)。
也不解析 ls
. 。曾经。使用通配符或 find
反而: http://mywiki.wooledge.org/ParsingLs
使用 find
对于需要递归的所有内容和一个简单的循环,以及用于其他所有内容的 glob:
find /foo -exec sh -c 'grep "$1" > "$1.out"' -- {} \;
或非递归:
for file in *; do grep "$file" > "$file.out"; done
注意引号的正确使用。
其他提示
一个解决方案没有 xargs
如下:
find . -mindepth 1 -maxdepth 1 -type f -exec sh -c "grep ABC '{}' > '{}.out'" \;
...同样可以做到 和 xargs
, ,事实证明:
ls -1 | xargs -I {} sh -c "grep ABC '{}' > '{}.out'"
编辑: :备注后添加单引号 卢纳特.
我想你的例子仅仅是个例子,你可能需要>其他东西。 GNU并行 http://www.gnu.org/software/parallel/ 可能是你的救援。它不需要额外的报价只要你的文件名不包含\ N:
ls | parallel "grep ABC {} > {}.out"
如果你有\ n的文件名在它:
find . -print0 | parallel -0 "grep ABC {} > {}.out"
作为额外的奖励,你得到的作业并行运行。
编辑。
可以安装GNU并行简单地通过:
wget http://git.savannah.gnu.org/cgit/parallel.git/plain/src/parallel
chmod 755 parallel
观看介绍视频了解详情: http://pi.dk/1
10秒安装:
wget pi.dk/3 -qO - | sh -x