如何在xargs命令中使用>?

Jes*_*ieh 150 bash redirect xargs

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

ls -1 | xargs -I{} "grep ABC '{}' > '{}'.out"
Run Code Online (Sandbox Code Playgroud)

但是,据我所知,xargs不喜欢双引号.但是,如果我删除双引号,则命令会将整个命令的输出重定向到名为"{}"的单个文件.而不是一系列单个文件.

有没有人知道使用xargs做到这一点的方法?我只是用这个grep场景作为例子来说明我对xargs的问题,所以任何不使用xargs的解决方案都不适用于我.

lhu*_*ath 185

不要犯下这样做的错误:

sh -c "grep ABC {} > {}.out"
Run Code Online (Sandbox Code Playgroud)

这将在很多条件下破解,包括时髦的文件名,并且无法正确引用.您{}必须始终是命令的一个完全独立的参数,以避免代码注入错误.你需要做的是这样的:

xargs -I{} sh -c 'grep ABC "$1" > "$1.out"' -- {}
Run Code Online (Sandbox Code Playgroud)

适用于xargs以及find.

顺便说一句,永远不要使用没有-0选项的xargs (除非非常罕见和受控的一次性交互使用,你不担心破坏你的数据).

也不要解析ls.永远.使用globbing或find代替:http://mywiki.wooledge.org/ParsingLs

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

find /foo -exec sh -c 'grep "$1" > "$1.out"' -- {} \;
Run Code Online (Sandbox Code Playgroud)

或非递归的:

for file in *; do grep "$file" > "$file.out"; done
Run Code Online (Sandbox Code Playgroud)

注意正确使用引号.

  • @legends2k 因为当您不使用 `-0` 时,`xargs` 将使用您的文件名并打破其中的所有空格、引号和反斜杠。你应该忘记 `xargs` 作为一个工具。如果您有行,请使用 bash 循环来迭代这些行:`while read line; 做 <命令> "$REPLY"; done < file-with-lines` 或 `command | 而...` (3认同)
  • +1。确实,我不应该忘记报价。 (2认同)
  • 尽管我很欣赏这个特定用例的详细解释,但问题是关于重定向“xargs”的输出,这并不总是涉及解析“ls”或使用“sh -c” ``。这根本没有回答这个问题,而是这个问题的第一个谷歌结果,只会增加混乱。 (2认同)
  • @Ihunath,嗨,你的回答对我来说很有效。但是您能否提供有关“xargs -I{} sh -c 'grep ABC "$1" > "$1.out"' -- {}`的详细解释或链接?特别是嵌入(双)引号和末尾的“--”符号的规则。谢谢 (2认同)
  • @lhunath 实际上 -- 符号没有什么特别的。当用命令执行 sh 时,所提供的参数被赋值为 $0、$1 等。当用脚本执行 sh 时(例如``sh test.sh```),脚本的名称被赋值为 $0 和第一个参数为 $1 等等。因此,保存在脚本中并执行的相同命令最终会改变其所有参数。使用 -- (或 _ 或 Turnip)作为一次性变量,允许您统一从偏移量 1 处开始参数。该命令可以不带 -- 编写,而是使用 $0 代替。 (2认同)

Ste*_*202 39

没有的解决方案xargs如下:

find . -mindepth 1 -maxdepth 1 -type f -exec sh -c "grep ABC '{}' > '{}.out'" \;
Run Code Online (Sandbox Code Playgroud)

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

ls -1 | xargs -I {} sh -c "grep ABC '{}' > '{}.out'"
Run Code Online (Sandbox Code Playgroud)

编辑:lhunath发表评论后添加单引号.


Ole*_*nge 13

我假设你的例子只是一个例子,你可能需要>其他的东西.GNU Parallel http://www.gnu.org/software/parallel/可能是你的救援.只要您的文件名不包含\n,它就不需要额外的引用:

ls | parallel "grep ABC {} > {}.out"
Run Code Online (Sandbox Code Playgroud)

如果您的文件名包含\n:

find . -print0 | parallel -0 "grep ABC {} > {}.out"
Run Code Online (Sandbox Code Playgroud)

作为额外的奖励,您可以并行运行作业.

编辑.

您可以通过以下方式安装GNU Parallel:

$ (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
Run Code Online (Sandbox Code Playgroud)

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

10秒安装:

ls | parallel "grep ABC {} > {}.out"
Run Code Online (Sandbox Code Playgroud)

  • 默认情况下不发货,许多存储库中没有可用的:( (3认同)