说我有一个带hi.txt和blah.txt的目录,我在linux-ish命令行上执行以下命令
ls *.* | xargs -t -i{} echo {}
您将看到的输出是
echo blah.txt
blah.txt
echo hi.txt
hi.txt
我想重定向stderr输出(比如'echo blah.txt'失败...),只留下xargs -t命令的输出写入std out,但它看起来好像也是stderr。
ls *.* | xargs -t -i{} echo {} 2> /dev/null
有没有办法控制它,让它输出到stdout?
答案 0 :(得分:3)
使用:
ls | xargs -t -i{} echo {} 2>&1 >/dev/null
2>&1
将标准错误从xargs
发送到标准输出当前的位置; >/dev/null
将原始标准输出发送到/dev/null
。因此,最终结果是标准输出包含echo命令,/dev/null
包含文件名。我们可以讨论文件名中的空格以及是否更容易使用sed
脚本将'echo'放在每行的前面(没有-t
选项),或者是否可以使用:
ls | xargs -i{} echo echo {}
(已测试:Solaris 10,Korn Shell;应该适用于其他shell和Unix平台。)
如果您不介意查看命令的内部工作原理,我确实设法将xargs
的错误输出与执行的命令的错误输出隔离开来。
al * zzz | xargs -t 2>/tmp/xargs.stderr -i{} ksh -c "ls -dl {} 2>&1"
(非标准)命令al
每行列出一个参数:
for arg in "$@"; do echo "$arg"; done
第一次重定向(2>/tmp/xargs.stderr
)将xargs
的错误输出发送到文件/tmp/xargs.stderr
。执行的命令是“ksh -c "ls -dl {} 2>&1"
”,它使用Korn shell在文件名上运行ls -ld
,并将任何错误输出转到标准输出。
/tmp/xargs.stderr
中的输出如下:
ksh -c ls -dl x1 2>&1
ksh -c ls -dl x2 2>&1
ksh -c ls -dl xxx 2>&1
ksh -c ls -dl zzz 2>&1
我使用“ls -ld
”代替echo
以确保我测试错误 - 文件x1
,x2
和xxx
已存在,但zzz
没有。
标准输出的输出如下:
-rw-r--r-- 1 jleffler rd 1020 May 9 13:05 x1
-rw-r--r-- 1 jleffler rd 1069 May 9 13:07 x2
-rw-r--r-- 1 jleffler rd 87 May 9 20:42 xxx
zzz: No such file or directory
在没有包含在'ksh -c "..."
'中的命令的情况下运行时,I / O重定向作为参数传递给命令('ls -ld
'),因此报告它无法找到文件“2>&1
”。也就是说,xargs
本身并没有使用shell来进行I / O重定向。
可以安排各种其他重定向,但基本问题是xargs
没有规定将自己的错误输出与它执行的命令分开,因此很难做到。 / p>
另一个相当明显的选择是使用xargs
编写shell脚本,然后让shell执行它。这是我之前展示的选项:
ls | xargs -i{} echo echo {} >/tmp/new.script
然后,您可以使用以下命令查看命令:
cat /tmp/new.script
您可以使用以下命令运行命令以丢弃错误:
sh /tmp/new.script 2>/dev/null
并且,如果您不想查看命令的标准输出,请将1>&2
附加到命令的末尾。
答案 1 :(得分:2)
所以我相信你想要的是stdout
您想忽略由...生成的stderr流 执行效用。
如果我错了,请纠正我。
首先,让我们创建一个更好的测试实用程序:
% cat myecho
#!/bin/sh
echo STDOUT $@
echo STDERR $@ 1>&2
% chmod +x myecho
% ./myecho hello world
STDOUT hello world
STDERR hello world
% ./myecho hello world >/dev/null
STDERR hello world
% ./myecho hello world 2>/dev/null
STDOUT hello world
%
所以现在我们有一些实际输出到stdout和stderr的东西,所以我们 可以肯定我们只是得到了我们想要的东西。
执行此操作的切线方法不是使用xargs,而是使用make。回应命令 然后这样做是有道理的。那是它的包。
% cat Makefile
all: $(shell ls *.*)
$(shell ls): .FORCE
./myecho $@ 2>/dev/null
.FORCE:
% make
./myecho blah.txt 2>/dev/null
STDOUT blah.txt
./myecho hi.txt 2>/dev/null
STDOUT hi.txt
% make >/dev/null
%
如果您使用xargs,那么您需要修改您的实用程序
xargs用它来压低stderr。然后你可以使用其他2>&1
技巧
已经提到过从stderr移动xargs -t生成的命令列表
到stdout。
% cat myecho2
#!/bin/sh
./myecho $@ 2>/dev/null
% chmod +x myecho2
% ./myecho2 hello world
STDOUT hello world
% ls *.* | xargs -t -i{} ./myecho2 {} 2>&1
./myecho blah.txt 2>/dev/null
STDOUT blah.txt
./myecho hi.txt 2>/dev/null
STDOUT hi.txt
% ls *.* | xargs -t -i{} ./myecho2 {} 2>&1 | tee >/dev/null
%
所以这种方法有效,并且会折叠你想要stdout的一切(忽略你不想要的东西)。
如果你发现自己做了很多,你可以编写一个通用实用程序来压制stderr:
% cat surpress_stderr
#!/bin/sh
$@ 2>/dev/null
% ./surpress_stderr ./myecho hello world
STDOUT hello world
% ls *.* | xargs -t -i{} ./surpress_stderr ./myecho {} 2>&1
./surpress_stderr ./myecho blah.txt 2>/dev/null
STDOUT blah.txt
./surpress_stderr ./myecho hi.txt 2>/dev/null
STDOUT hi.txt
%
答案 2 :(得分:1)
看起来xargs -t会转到stderr,而且你无能为力。
你可以这样做:
ls | xargs -t -i{} echo "Foo: {}" >stderr.txt | tee stderr.txt
在命令运行时仅显示终端上的stderr数据,然后通过stderr.txt grep查看是否发生了意外情况,沿grep -v Foo: stderr.txt
另请注意,在Unix上,ls *.*
不是您显示所有内容的方式。如果您想查看所有文件,只需自行运行ls
。
答案 3 :(得分:1)
xargs -t
回显在执行之前要对stderr执行的命令。如果你希望它们回显到stderr,你可以使用2>&1
构造将stderr传递给stdout:
ls *.* | xargs -t -i{} echo {} 2>&1
答案 4 :(得分:0)
据我所知,使用GNU Parallel http://www.gnu.org/software/parallel/的问题会做正确的事情:
ls *.* | parallel -v echo {} 2> /dev/null