Terminer complètement la sortie de la command avant de passer à une autre command?

Existe-t-il un moyen d'exécuter uniquement une command après l'autre sans un file temporaire? J'ai une plus longue command en cours d'exécution et une autre command qui formate la sortie et l'envoie à un server HTTP en utilisant curl. Si je viens d'exécuter la commandA | commandB commandA | commandB , la command commandB va se curl , se connecter au server et commencer à envoyer des données. Parce que la commandA prend autant de time, le server HTTP commandA . Je peux faire ce que je veux avec commandA > /tmp/file && commandB </tmp/file && rm -f /tmp/file

Par curiosité, je veux savoir s'il existe un moyen de le faire sans le file temporaire. J'ai essayé mbuffer -m 20M -q -P 100 mais le process curl est toujours démarré dès le début. Mbuffer attend jusqu'à commandA que la commandA soit terminée avec l'envoi des données. (Les données elles-mêmes ne sont que quelques centaines de kb au maximum)

Ceci est similaire à quelques-unes des autres réponses. Si vous avez le package "moreutils", vous devriez avoir la command sponge . essayer

 commandA | sponge | { read -rx; { printf "%s\n" "$x"; cat; } | commandB; } 

La command sponge est fondamentalement un filter de passage (comme le cat ) sauf qu'elle ne commence pas à écrire la sortie tant qu'elle n'a pas lu l'input entière. C'est-à-dire qu'il «absorbe» datatables, puis les libère lorsque vous les pressez (comme une éponge). Donc, dans une certaine mesure, c'est "sortingcher" – s'il y a une quantité non négligeable de données, sponge utilise certainement un file temporaire. Mais c'est invisible pour toi; vous n'avez pas à vous soucier de l'entretien ménager des choses comme le choix d'un nom de file unique et le nettoyage par la suite.

Le { read -rx; { printf "%s\n" "$x"; cat; } | commandB; } { read -rx; { printf "%s\n" "$x"; cat; } | commandB; } { read -rx; { printf "%s\n" "$x"; cat; } | commandB; } lit la première ligne de sortie de l' sponge . Rappelez-vous que cela n'apparaît pas tant que la commandA n'est pas terminée. Ensuite, il triggers la commandB , écrit la première ligne sur la pipe et appelle cat pour lire le rest de la sortie et l'écrire dans le tuyau.

Je ne connais aucun utilitaire UNIX standard qui puisse résoudre ce problème. Une option serait d'utiliser awk pour accumuler la sortie commandA et la vider à la commandB en un seul coup, comme si

 commandA | awk '{x = x ORS $0}; END{printf "%s", x | "commandB"}' 

Attention, cela pourrait être gourmand en memory puisque awk crée une string à partir de son input.

Les commands de pipe line sont lancées en même time, vous devez stocker la sortie commandA quelque part pour l'utiliser plus tard. Vous pouvez éviter le file temporaire en utilisant la variable:

 output=$(command A; echo A) printf '%s' "${output%%A}" | commandB 

Vous pouvez résoudre l'exigence avec un petit script. Cette variante particulière évite le file temporaire et le potentiel memory hog au désortingment des process supplémentaires.

 #!/bin/bash # IFS= read LINE if test -n "$LINE" then test -t 2 && echo "Starting $*" >&2 ( echo "$LINE" cat ) | "$@" else exit 0 fi 

Si vous deviez appeler le script waituntil (et le rendre exécutable, le mettre dans le PATH , etc.), vous l'utiliserez comme ceci

 commandA... | waituntil commandB... 

Exemple

 ( sleep 3 ; date ; id ) | waituntil nl