Frage

sagen, ich habe ein Verzeichnis mit hi.txt und blah.txt und ich führen Sie den folgenden Befehl auf einer Linux-ish Befehlszeile

ls *.* | xargs -t -i{} echo {}

die Ausgabe sehen Sie, ist

echo blah.txt
blah.txt
echo hi.txt
hi.txt

Ich möchte die stderr-Ausgabe umleiten (sagen ‚echo blah.txt‘ nicht ...), nur die Ausgabe von dem xargs -t Befehl verlassen geschrieben std, aber es sieht aus, als ob es stderr als auch ist.

ls *.* | xargs -t -i{} echo {} 2> /dev/null

Gibt es eine Möglichkeit, es zu kontrollieren, um es Ausgabe an stdout?

War es hilfreich?

Lösung

So glaube ich, was Sie wollen, ist zu haben, wie stdout

  • die stdout aus dem Dienstprogramm, das xargs ausführt
  • die Liste der Befehle, die von xargs erzeugt -t

Sie möchten den Stderr Strom durch die erzeugte ignorieren ausgeführt Dienstprogramm.

Bitte korrigieren Sie mich, wenn ich falsch bin.

Lassen Sie uns zunächst einen besseren Test-Utility erstellen:

% 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
%

So, jetzt haben wir etwas, das tatsächlich sowohl stdout ausgibt und stderr, so dass wir Zwar können wir nur bekommen, was wir wollen.

Ein tangentialer Weg, dies zu tun, ist nicht xargs zu verwenden, sondern macht. In Anlehnung an einen Befehl und dann tut es ist irgendwie was machen tut. Das ist seine Tasche.

% 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
% 

Wenn Sie mit xargs gebunden sind, dann müssen Sie Ihre Nützlichkeit modifizieren, dass xargs verwendet, so dass es Unterdrückt stderr. Dann können Sie die 2>&1 Trick andere verwenden den Befehl bewegen Inserat von xargs erzeugt -t von stderr haben erwähnt, auf die Standardausgabe.

% 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
%

So funktioniert dieser Ansatz, und bricht zusammen alles, was Sie wollen stdout (Weglassen, was Sie nicht wollen).

Wenn Sie sich selbst finden dies zu tun viel, können Sie eine allgemeine Nützlichkeit schreiben stderr surpress:

% 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
%

Andere Tipps

Verwendung:

ls | xargs -t -i{} echo {} 2>&1 >/dev/null

Die 2>&1 sendet den Standardfehler von xargs, wo die Standardausgabe wird derzeit gehen; die >/dev/null sendet die ursprüngliche Standardausgabe /dev/null. So ist das Nettoergebnis, dass die Standardausgabe enthält die Echo-Befehle und /dev/null enthält die Dateinamen. Wir können über Leerzeichen in Dateinamen diskutieren und ob es einfacher wäre, einen sed Skript zu verwenden zu setzen ‚Echo‘ an der Vorderseite jeder Zeile (ohne -t Option), oder ob Sie könnten verwendet werden:

ls | xargs -i{} echo echo {}

(getestet. Solaris 10, Korn Shell, sollte auf anderen Schalen und Unix-Plattformen)


Wenn Sie nichts dagegen nicht das Innenleben der Befehle zu sehen, ich habe es geschafft, die Fehlerausgabe von xargs und die Fehlerausgabe des Befehls ausgeführt zu trennen.

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

Der (Nicht-Standard) Befehl al listet seine Argumente pro Zeile ein:

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

Die erste Umleitung (2>/tmp/xargs.stderr) sendet die Fehlerausgabe von xargs in die Datei /tmp/xargs.stderr. Der Befehl ausgeführt ist ‚ksh -c "ls -dl {} 2>&1"‘, die das Korn-Shell verwendet ls -ld auf den Dateinamen mit jeder Fehlerausgabe geht auf der Standardausgabe auszuführen.

Der Ausgang in /tmp/xargs.stderr wie folgt aussieht:

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

verwendet I 'ls -ld' anstelle von echo, um sicherzustellen, ich teste Fehler -. Die Dateien x1, x2 und xxx existierte, aber zzz nicht

Die Ausgabe auf der Standardausgabe sah aus wie:

-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

Wenn ohne den Befehl eingewickelt in ‚ksh -c "..."‘ laufen, die I / O-Umleitung wurde als Argument für den Befehl ( ‚ls -ld‘) geführt und berichtet daher, dass es nicht die Datei ‚2>&1‘ gefunden. Das heißt, xargs hat sich nicht die Shell verwenden, um die E / A-Umleitung zu tun.

Es wäre möglich, für verschiedene andere Umleitungen zu arrangieren, aber das grundlegende Problem ist, dass xargs seinen eigenen Fehlerausgang keine Bestimmung macht aus, dass die Befehle zur Trennung führt sie, so ist es schwer zu tun.

Die andere ziemlich offensichtliche Option ist xargs zu verwenden, um ein Shell-Skript zu schreiben, und haben dann die Shell ausführen. Dies ist die Option, die ich zeigte vor:

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

Sie können dann sehen Sie die Befehle mit:

cat /tmp/new.script

Sie können die Befehle ausführen, um die Fehler mit verwerfen:

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

Und wenn Sie nicht wollen, entweder, hängen 1>&2 an das Ende des Befehls die Standardausgabe von den Befehlen sehen.

xargs -t echos die Befehle vor der Ausführung sie in stderr ausgeführt werden. Wenn Sie sie wollen stderr statt echo können Sie Rohr stderr mit dem 2>&1 Konstrukt nach stdout:

ls *.* | xargs -t -i{} echo {} 2>&1

Es sieht aus wie xargs -t nach stderr geht, und es gibt nicht viel können Sie dagegen tun können.

Sie können tun:

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

nur die stderr Daten auf dem Endgerät als Befehl ausgeführt wird, um anzuzeigen, und dann durch stderr.txt grep nach, um zu sehen, ob etwas unerwartet aufgetreten ist, entlang der Linien von grep -v Foo: stderr.txt

Beachten Sie auch, dass auf Unix, ls *.* ist nicht, wie Sie alles, was angezeigt werden soll. Wenn Sie alle Dateien sehen wollen, nur läuft ls auf seinem eigenen.

Wie ich verstehe Ihr Problem mit GNU Parallel http://www.gnu.org/software/ parallel / würde das richtige tun:

ls *.* | parallel -v echo {} 2> /dev/null
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top