Je travaille avec un utilitaire de ligne de commande qui nécessite de passer le nom d'un fichier pour écrire la sortie, par exemple.
foo -o output.txt
La seule chose qu'il écrit dans stdout
est un message qui indique qu'il s'est exécuté correctement. J'aimerais pouvoir diriger tout ce qui est écrit dans output.txt
vers un autre utilitaire de ligne de commande. Ma motivation est que output.txt finira par être un fichier de 40 Go que je n'ai pas besoin de conserver, et je préfère diriger les flux plutôt que de travailler sur des fichiers massifs de manière progressive.
Existe-t-il un moyen dans ce scénario de diriger la sortie réelle (c'est-à-dire output.txt
) à une autre commande? Puis-je en quelque sorte passer magiquement stdout
comme argument de fichier?
La manière la plus pratique de procéder consiste à utiliser la substitution de processus. Dans bash, la syntaxe se présente comme suit:
foo -o >(other_command)
(Notez qu'il s'agit d'un bashisme . Il existe des solutions similaires pour d'autres coquilles, mais en fin de compte, ce n'est pas portable.)
Vous pouvez faire ce qui précède explicitement/manuellement comme suit:
Créez un canal nommé à l'aide de la commande mkfifo
.
mkfifo my_buf
Lancez votre autre commande avec ce fichier en entrée
other_command < my_buf
Exécutez foo
et laissez-le écrire sa sortie dans my_buf
foo -o my_buf
/dev/stdout
Vous pouvez également utiliser le fichier de l'appareil /dev/stdout
comme suit
foo -o /dev/stdout | other_command
Les canaux nommés fonctionnent bien, mais vous avez une syntaxe plus agréable et plus directe disponible via la substitution de processus bash qui a l'avantage supplémentaire de ne pas utiliser un canal nommé permanent qui doit être supprimé plus tard (la substitution de processus utilise des canaux nommés temporaires dans les coulisses):
foo -o >(other command)
De plus, si vous souhaitez diriger la sortie vers votre commande et également enregistrer la sortie dans un fichier, vous pouvez le faire:
foo -o >(tee output.txt) | other command
Dans le but de rendre stackoverflow heureux, laissez-moi écrire une phrase suffisamment longue car ma solution proposée ne comporte que 18 caractères au lieu des 30+ requis
foo -o /dev/stdout
Vous pouvez utiliser la magie d'UNIX et créer un canal nommé :)
Créer le tuyau
$ mknod -p mypipe
Démarrer le processus qui lit à partir du tuyau
$ second-process < mypipe
Démarrer le processus, qui écrit dans le tuyau
$ foo -o mypipe
J'utilise/dev/tty comme nom de fichier de sortie, ce qui équivaut à utiliser/dev/nul/lorsque vous ne voulez rien produire du tout. Alors | et vous avez terminé.