web-dev-qa-db-fra.com

passer stdout comme nom de fichier pour l'utilitaire de ligne de commande?

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?

33
Jake

Solution 1: utiliser substitution de processus

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.)

Solution 2: utiliser canaux nommés explicitement

Vous pouvez faire ce qui précède explicitement/manuellement comme suit:

  1. Créez un canal nommé à l'aide de la commande mkfifo.

    mkfifo my_buf
    
  2. Lancez votre autre commande avec ce fichier en entrée

    other_command < my_buf
    
  3. Exécutez foo et laissez-le écrire sa sortie dans my_buf

    foo -o my_buf
    

Solution 3: utilisation de /dev/stdout

Vous pouvez également utiliser le fichier de l'appareil /dev/stdout comme suit

foo -o /dev/stdout | other_command
38
aioobe

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

48
frankc

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
31
Nestor Urquiza

Vous pouvez utiliser la magie d'UNIX et créer un canal nommé :)

  1. Créer le tuyau

    $ mknod -p mypipe
    
  2. Démarrer le processus qui lit à partir du tuyau

    $ second-process < mypipe
    
  3. Démarrer le processus, qui écrit dans le tuyau

    $ foo -o mypipe
    
5
ktf

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é.

0
Jaime Garza