如何使用> 在 xargs 命令中?

发布于 2024-07-19 14:34:20 字数 341 浏览 8 评论 0原文

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

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

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

有谁知道使用 xargs 执行此操作的方法吗? 我只是使用这个 grep 场景作为示例来说明我的 xargs 问题,因此任何不使用 xargs 的解决方案都不适合我。

I want to find a bash command that will let me grep every file in a directory and write the output of that grep to a separate file. My guess would have been to do something like this

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

but, as far as I know, xargs doesn't like the double-quotes. If I remove the double-quotes, however, then the command redirects the output of the entire command to a single file called '{}'.out instead of to a series of individual files.

Does anyone know of a way to do this using xargs? I just used this grep scenario as an example to illustrate my problem with xargs so any solutions that don't use xargs aren't as applicable for me.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

掀纱窥君容 2024-07-26 14:34:21

不要犯这样的错误:

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

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

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

适用于 xargs 以及 find

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

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

使用 find 处理所有需要递归和带有 glob for 的简单循环其他一切:

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

或非递归:

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

注意引号的正确使用。

Do not make the mistake of doing this:

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

This will break under a lot of conditions, including funky filenames and is impossible to quote right. Your {} must always be a single completely separate argument to the command to avoid code injection bugs. What you need to do, is this:

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

Applies to xargs as well as find.

By the way, never use xargs without the -0 option (unless for very rare and controlled one-time interactive use where you aren't worried about destroying your data).

Also don't parse ls. Ever. Use globbing or find instead: http://mywiki.wooledge.org/ParsingLs

Use find for everything that needs recursion and a simple loop with a glob for everything else:

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

or non-recursive:

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

Notice the proper use of quotes.

羞稚 2024-07-26 14:34:21

没有 xargs 的解决方案如下:

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

...使用 xargs 也可以实现同样的效果,结果是:

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

编辑< /em>:lhunath

A solution without xargs is the following:

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

...and the same can be done with xargs, it turns out:

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

Edit: single quotes added after remark by lhunath.

清风疏影 2024-07-26 14:34:21

我假设您的示例只是一个示例,您可能需要 > 对于其他事情。 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 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 的服务器,请尝试 parallel --embed

I assume your example is just an example and that you may need > for other things. GNU Parallel http://www.gnu.org/software/parallel/ may be your rescue. It does not need additional quoting as long as your filenames do not contain \n:

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

If you have filenames with \n in it:

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

As an added bonus you get the jobs run in parallel.

Watch the intro videos to learn more: http://pi.dk/1

The 10 seconds installation will try to do a full installation; if that fails, a personal installation; if that fails, a minimal installation:

$ (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

If you need to move it to a server, that does not have GNU Parallel installed, try parallel --embed.

深陷 2024-07-26 14:34:21

实际上,这里的大多数答案并不适用于所有文件名(如果它们包含双引号和单引号),包括 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"

Actually, most of the answers here do not work with all filenames (if they contain double and single quotes), including the answer by lhunath and Stephan202.

This solution works with filenames with single and double quotes:

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

Here's a test with filename with both single and double quotes:

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"
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文