bash 如何在 xargs 命令中使用 >?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/845863/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to use > in an xargs command?
提问by Jesse Shieh
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
我想找到一个 bash 命令,它可以让我 grep 目录中的每个文件并将该 grep 的输出写入一个单独的文件。我的猜测是做这样的事情
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.
但是,据我所知, xargs 不喜欢双引号。但是,如果我删除双引号,则该命令会将整个命令的输出重定向到名为“{}”.out 的单个文件,而不是一系列单独的文件。
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.
有谁知道使用 xargs 做到这一点的方法吗?我只是以这个 grep 场景为例来说明我的 xargs 问题,因此任何不使用 xargs 的解决方案都不适用于我。
回答by lhunath
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 "" > ".out"' -- {}
Applies to xargs
as well as find
.
适用于xargs
以及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).
顺便说一句,不要在没有-0
选项的情况下使用 xargs (除非用于非常罕见且受控的一次性交互式使用,您不必担心破坏数据)。
Also don't parse ls
. Ever. Use globbing or find
instead: http://mywiki.wooledge.org/ParsingLs
也不要解析ls
。曾经。使用通配或find
代替:http://mywiki.wooledge.org/ParsingLs
Use find
for everything that needs recursion and a simple loop with a glob for everything else:
使用find
的需要递归和一个简单的循环与一切一水珠的一切:
find /foo -exec sh -c 'grep "" > ".out"' -- {} \;
or non-recursive:
或非递归:
for file in *; do grep "$file" > "$file.out"; done
Notice the proper use of quotes.
注意正确使用引号。
回答by Stephan202
A solution without xargs
is the following:
没有的解决方案xargs
如下:
find . -mindepth 1 -maxdepth 1 -type f -exec sh -c "grep ABC '{}' > '{}.out'" \;
...and the same can be done withxargs
, it turns out:
......而同样的做法可以用xargs
,事实证明:
ls -1 | xargs -I {} sh -c "grep ABC '{}' > '{}.out'"
Edit: single quotes added after remark by lhunath.
编辑:在lhunath评论后添加单引号。
回答by Ole Tange
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:
我假设您的示例只是一个示例,您可能需要 > 来处理其他事情。GNU Parallel http://www.gnu.org/software/parallel/可能是你的救星。只要您的文件名不包含 \n,它就不需要额外的引用:
ls | parallel "grep ABC {} > {}.out"
If you have filenames with \n in it:
如果您的文件名中包含 \n:
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:
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
If you need to move it to a server, that does not have GNU Parallel installed, try parallel --embed
.
如果您需要将其移动到未安装 GNU Parallel 的服务器,请尝试parallel --embed
.