1

hi.txt と blah.txt を含むディレクトリがあり、Linux っぽいコマンド ラインで次のコマンドを実行するとします。

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 に出力するように制御する方法はありますか?

4

5 に答える 5

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;他のシェルおよびUnixプラットフォームで動作するはずです。)


コマンドの内部動作を確認してもかまわない場合は、xargs実行されたコマンドのエラー出力とエラー出力を分離することができました。

al * zzz | xargs -t 2>/tmp/xargs.stderr -i{} ksh -c "ls -dl {} 2>&1"

(非標準)コマンドalは、引数を1行に1つずつリストします。

for arg in "$@"; do echo "$arg"; done

最初のリダイレクト(2>/tmp/xargs.stderr)は、エラー出力をからxargsファイルに送信します/tmp/xargs.stderr。実行されるコマンドは' ksh -c "ls -dl {} 2>&1"'です。これは、Kornシェルを使用し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、の代わりに''を使用しました。ファイル、、、およびが存在しましたが、そうではありません。echox1x2xxxzzz

標準出力の出力は次のようになりました。

-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、シェル自体を使用してI/Oリダイレクトを実行しませんでした。

他のさまざまなリダイレクトを手配することは可能ですが、基本的な問題は、xargsそれ自体のエラー出力を実行するコマンドのエラー出力から分離するための準備がないため、実行が難しいことです。

もう1つの明らかなオプションはxargs、シェルスクリプトを記述してから、シェルにそれを実行させることです。これは私が前に示したオプションです:

ls | xargs -i{} echo echo {} >/tmp/new.script

次に、次のコマンドを確認できます。

cat /tmp/new.script

次のコマンドを実行して、エラーを破棄できます。

sh /tmp/new.script 2>/dev/null

また、コマンドからの標準出力も表示したくない場合は、コマンド1>&2の最後に追加してください。

于 2009-05-09T01:28:54.147 に答える
2

だから私はあなたが望むのはstdoutがそうであることだと信じています

  • xargs が実行するユーティリティからの stdout
  • xargs -t によって生成されるコマンドのリスト

実行されたユーティリティによって生成された 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 を使用することです。コマンドをエコーし​​てから実行することは、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、 xargs -t によって生成されたコマンド リストを stderr から 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
%

したがって、このアプローチは機能し、必要なものをすべて標準出力に折りたたむ (不要なものを除外する)。

これを頻繁に行う場合は、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
%
于 2009-05-09T03:16:29.580 に答える
1

xargs -tはstderrに行くように見えますが、それについてできることはあまりありません。

あなたができること:

ls | xargs -t -i{} echo "Foo: {}" >stderr.txt | tee stderr.txt

コマンドの実行時に端末にstderrデータのみを表示し、その後stderr.txtをgrepして、予期しないことが発生したかどうかを確認します。grep -v Foo: stderr.txt

ls *.*また、Unixでは、すべてを表示する方法ではないことに注意してください。すべてのファイルを表示したい場合はls、単独で実行してください。

于 2009-05-09T01:05:54.887 に答える
1

xargs -t実行するコマンドを実行前に stderr にエコーします。2>&1代わりに stderr にエコーする場合は、次の構文を使用して stderr を stdout にパイプできます。

ls *.* | xargs -t -i{} echo {} 2>&1
于 2009-05-09T01:06:45.510 に答える
0

私が理解しているように、GNU Parallel http://www.gnu.org/software/parallel/を使用すると正しいことが行われます。

ls *.* | parallel -v echo {} 2> /dev/null
于 2010-06-10T19:39:14.340 に答える