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.
Un inconvénient à prendre en compte est que si ./a ou ./b échoue, l'appelant ne le découvrira pas.
Alexander Pogrebnyak le
5
L'OP a marqué la question bash, mais pour mémoire, cela ne fonctionne dans aucun autre shell. C'est une extension bash de la norme utilitaire Posix.
DigitalRoss
5
J'ai essayé cette solution avec un programme Java et obtenu cette erreur: -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?
styfle
1
@DigitalRoss - La solution peut être étendue à d'autres shells en utilisant un alias. Dans tcsh, la laideur suivante fonctionne: alias diffcmd bash -c \'diff \<\(sh -c \!:1\) \<\( sh -c \!:2 \)\'. (Puis par exemple: diffcmd "ls" "ls -a").
Paul Lynch
Pour quiconque se promène hors de Google, cela fonctionne également sous zsh. (De plus, si vous devez alimenter en entrée quelque chose qui appelle 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.)
ssokolow
26
En ajoutant aux deux réponses, si vous voulez voir une comparaison côte à côte, utilisez vimdiff:
vimdiffcrée des vues de comparaison des différences magnifiques, intelligentes et interactives. Il semble venir avec le vimpackage sur la plupart des systèmes.
Tim Visée
vimdiffmontre également non seulement la ligne qui diffère, mais également le fragment de texte spécifique qui diffère.
Vous feriez mieux de supprimer les tuyaux nommés après les avoir utilisés, avec rm a_fifo b_fifo.
Franklin Yu
15
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.
Cela ne fonctionne pas correctement pour le poisson. Si la sortie des programmes est supérieure à un BUFSIZ, la commande se bloquera. (ou poisson utilisera simplement un fichier temporaire sur le disque)
Evan Benn
7
En ajoutant un peu plus aux réponses déjà bonnes (m'a aidé!):
La commande dockerenvoie son aide àSTD_ERR (c.- -d. Descripteur de fichier 2)
Je voulais voir si docker attachet docker attach --helpdonner 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)
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 bcomppour ce qui précède (au lieu de bcompare) car bcomplance 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.
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.
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.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.
la source
-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
:Quelque chose comme ça:
la source
vimdiff
crée des vues de comparaison des différences magnifiques, intelligentes et interactives. Il semble venir avec levim
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) :
... mais la solution de John Kugelman est beaucoup plus propre.
la source
rm a_fifo b_fifo
.Pour toute personne curieuse, voici comment vous effectuez la substitution de processus en utilisant le Fish shell :
Frapper:
Poisson:
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.
la source
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
etdocker 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é.
la source
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:
Pour Beyond Compare, notez que vous devez utiliser
bcomp
pour ce qui précède (au lieu debcompare
) carbcomp
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:
et ce qui suit qui est la différence entre
$(...)
et=(...)
:la source