Question

dis que j'ai un répertoire avec hi.txt et blah.txt et que j'exécute la commande suivante sur une ligne de commande linux-ish

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

la sortie que vous verrez est

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

je voudrais rediriger la sortie stderr (par exemple, "echo blah.txt" échoue ...), ne laissant que la sortie de la commande xargs -t écrite sur std out, mais on dirait que c’est aussi stderr.

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

Y a-t-il un moyen de le contrôler, de le sortir en sortie sur stdout?

Était-ce utile?

La solution

Donc, je crois que ce que vous voulez, c'est d'avoir la sortie standard

  • la sortie standard de l'utilitaire que xargs exécute
  • la liste des commandes générées par xargs -t

Vous voulez ignorer le flux stderr généré par le utilitaire exécuté.

Corrigez-moi si je me trompe.

Premièrement, créons un meilleur utilitaire de test:

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

Alors maintenant, nous avons quelque chose qui génère des sorties vers stdout et stderr, nous peut être sûr que nous obtenons seulement ce que nous voulons.

Une façon tangente de faire cela est de ne pas utiliser xargs, mais plutôt de faire. En écho à une commande et puis le faire est un peu ce que make fait. C'est son sac.

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

Si vous êtes lié à l'utilisation de xargs, vous devez modifier votre utilitaire xargs utilise donc il surpasse stderr. Ensuite, vous pouvez utiliser le 2>&1 tour d'autres ont mentionné le déplacement de la liste de commandes générée par xargs -t à partir de stderr to 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
%

Cette approche fonctionne donc et réduit tout ce que vous voulez stdout (en laissant de côté ce que vous ne voulez pas).

Si vous vous trouvez souvent en train de faire cela, vous pouvez écrire un utilitaire général pour surpresser 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
%

Autres conseils

Utiliser:

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

Le 2>&1 envoie l'erreur standard de xargs à l'endroit où la sortie standard va actuellement; le >/dev/null envoie la sortie standard d'origine à /dev/null. Le résultat final est donc que la sortie standard contient les commandes echo et sed contient les noms de fichier. Nous pouvons débattre des espaces dans les noms de fichiers et déterminer s'il serait plus simple d'utiliser un script -t pour insérer "echo" au début de chaque ligne (sans option al), ou si vous pouvez utiliser:

ls | xargs -i{} echo echo {}

(testé: Solaris 10, Korn Shell; devrait fonctionner sur les autres shells et les plateformes Unix.)

Si cela ne vous dérange pas de voir le fonctionnement interne des commandes, j'ai réussi à séparer la sortie d'erreur de 2>/tmp/xargs.stderr et la sortie d'erreur de la commande exécutée.

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

La commande (non standard) /tmp/xargs.stderr liste ses arguments un par ligne:

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

La première redirection (ksh -c "ls -dl {} 2>&1") envoie la sortie d'erreur de ls -ld au fichier echo. La commande exécutée est 'x1', qui utilise le shell Korn pour exécuter x2 sur le nom du fichier. Toute sortie d'erreur passant à la sortie standard.

La sortie dans xxx ressemble à:

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

J'ai utilisé 'zzz' à la place de ksh -c "..." pour vérifier que je testais les erreurs - les fichiers 1>&2, <=> et <=> existaient, mais <=> n'existe pas.

La sortie sur la sortie standard ressemblait à:

-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

Lorsqu’il est exécuté sans la commande encapsulée dans '<=>', la redirection des E / S a été transmise en tant qu’argument à la commande ('<=>'). Il a donc été signalé qu’il n’était pas possible de trouver le fichier '< => '. C’est-à-dire que <=> n’a pas utilisé le shell pour effectuer la redirection des E / S.

Il serait possible d'organiser diverses autres redirections, mais le problème fondamental est que <=> ne permet pas de séparer sa propre sortie d'erreur de celle des commandes qu'il exécute. Il est donc difficile à faire.

L’autre option assez évidente consiste à utiliser <=> pour écrire un script shell, puis le faire exécuter par le shell. C’est l’option que j’ai déjà montrée:

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

Vous pouvez alors voir les commandes avec:

cat /tmp/new.script

Vous pouvez exécuter les commandes pour supprimer les erreurs avec:

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

Et si vous ne voulez pas voir la sortie standard des commandes, ajoutez <=> à la fin de la commande.

xargs -t renvoie les commandes à exécuter à stderr avant de les exécuter. Si vous souhaitez qu’ils répercutent sur stderr, vous pouvez rediriger stderr vers stdout avec la construction 2>&1:

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

On dirait que xargs -t va dans stderr, et vous ne pouvez rien y faire.

Vous pourriez faire:

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

pour n'afficher que les données stderr sur votre terminal pendant l'exécution de votre commande, puis passer de grep à stderr.txt après pour voir si quelque chose d'inattendu s'est produit, selon les lignes de grep -v Foo: stderr.txt

Notez également que sous Unix, ls *.* n’affiche pas tout. Si vous souhaitez voir tous les fichiers, exécutez simplement ls seul.

Si je comprends bien votre problème avec GNU Parallel, http://www.gnu.org/software/ parallel / ferait le bon choix:

ls *.* | parallel -v echo {} 2> /dev/null
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top