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