Disons que j'ai trop de programmes a
et b
que je peux courir avec ./a
et./b
.
Est-il possible de différencier leurs sorties sans écrire au préalable dans des fichiers temporaires?
Disons que j'ai trop de programmes a
et b
que je peux courir avec ./a
et./b
.
Est-il possible de différencier leurs sorties sans écrire au préalable dans des fichiers temporaires?
Réponses:
Utilisez <(command)
pour transmettre la sortie d'une commande à un autre programme comme s'il s'agissait d'un nom de fichier. Bash dirige la sortie du programme vers un tube et passe un nom de fichier comme /dev/fd/63
à la commande externe.
diff <(./a) <(./b)
De même, vous pouvez utiliser >(command)
si vous souhaitez diriger quelque chose dans une commande.
Cela s'appelle «Process Substitution» dans la page de manuel de Bash.
-bash: syntax error near unexpected token ('
. J'ai essayé à nouveau sans parenthèse et j'ai obtenu -bash: java: No such file or directory
. Cela ne fonctionne-t-il pas si la commande a des paramètres?
alias diffcmd bash -c \'diff \<\(sh -c \!:1\) \<\( sh -c \!:2 \)\'
. (Puis par exemple: diffcmd "ls" "ls -a").
fseek
, zsh propose =(./a)
qui peut être utilisé de manière identique <(./a)
mais utilise un fichier temporaire sous le capot, que zsh supprimera pour vous.)
En ajoutant aux deux réponses, si vous voulez voir une comparaison côte à côte, utilisez vimdiff
:
vimdiff <(./a) <(./b)
Quelque chose comme ça:
vimdiff
crée des vues de comparaison des différences magnifiques, intelligentes et interactives. Il semble venir avec le vim
package sur la plupart des systèmes.
vimdiff
montre également non seulement la ligne qui diffère, mais également le fragment de texte spécifique qui diffère.
Une option serait d'utiliser des tubes nommés (FIFO) :
mkfifo a_fifo b_fifo
./a > a_fifo &
./b > b_fifo &
diff a_fifo b_fifo
... mais la solution de John Kugelman est beaucoup plus propre.
rm a_fifo b_fifo
.
Pour toute personne curieuse, voici comment vous effectuez la substitution de processus en utilisant le Fish shell :
Frapper:
diff <(./a) <(./b)
Poisson:
diff (./a | psub) (./b | psub)
Malheureusement, la mise en œuvre dans les poissons est actuellement insuffisante ; fish se bloque ou utilise un fichier temporaire sur le disque. Vous ne pouvez pas non plus utiliser psub pour la sortie de votre commande.
En ajoutant un peu plus aux réponses déjà bonnes (m'a aidé!):
La commande docker
envoie son aide àSTD_ERR
(c.- -d. Descripteur de fichier 2)
Je voulais voir si docker attach
et docker attach --help
donner le même résultat
$ docker attach
$ docker attach --help
Après avoir tapé ces deux commandes, j'ai fait ce qui suit:
$ diff <(!-2 2>&1) <(!! 2>&1)
!! est le même que! -1 ce qui signifie exécuter la commande 1 avant celle-ci - la dernière commande
! -2 signifie exécuter la commande deux avant celle-ci
2> & 1 signifie envoyer la sortie file_descriptor 2 (STD_ERR) au même endroit que la sortie file_descriptor 1 (STD_OUT)
J'espère que cela a été d'une certaine utilité.
Pour zsh, l'utilisation =(command)
crée automatiquement un fichier temporaire et le remplace =(command)
par le chemin du fichier lui-même. Avec la substitution de processus normale, $(command)
est remplacé par la sortie de la commande.
Cette fonctionnalité zsh est très utile et peut être utilisée comme ceci pour comparer la sortie de deux commandes à l'aide d'un outil de diff, par exemple Beyond Compare:
bcomp =(ulimit -Sa | sort) =(ulimit -Ha | sort)
Pour Beyond Compare, notez que vous devez utiliser bcomp
pour ce qui précède (au lieu de bcompare
) car bcomp
lance la comparaison et attend qu'elle se termine. Si tu utilisesbcompare
, cela lance la comparaison et se termine immédiatement en raison de quoi les fichiers temporaires créés pour stocker la sortie des commandes disparaissent.
En savoir plus ici: http://zsh.sourceforge.net/Intro/intro_7.html
Notez également ceci:
Notez que le shell crée un fichier temporaire et le supprime lorsque la commande est terminée.
et ce qui suit qui est la différence entre $(...)
et =(...)
:
Si vous lisez la page de manuel de zsh, vous remarquerez peut-être que <(...) est une autre forme de substitution de processus similaire à = (...). Il y a une différence importante entre les deux. Dans le cas <(...), le shell crée un tube nommé (FIFO) au lieu d'un fichier. C'est mieux, car cela ne remplit pas le système de fichiers; mais cela ne fonctionne pas dans tous les cas. En fait, si nous avions remplacé = (...) par <(...) dans les exemples ci-dessus, tous auraient cessé de fonctionner sauf pour fgrep -f <(...). Vous ne pouvez pas modifier un tube ou l'ouvrir en tant que dossier de messagerie; fgrep, cependant, n'a aucun problème à lire une liste de mots à partir d'un tube. Vous vous demandez peut-être pourquoi diff <(foo) bar ne fonctionne pas, puisque foo | diff - barre fonctionne; c'est parce que diff crée un fichier temporaire s'il remarque que l'un de ses arguments est -, puis copie son entrée standard dans le fichier temporaire.