How can I parse output of a single command by multiple commands without truncating at each step?

For example ls -al|grep -i something will pass every line that has "something" in it to the next pipe which is fine, but that also means every other line in the pipe is discarded since there wont be matching the condition. What I want is to be able to operate on single pipe by many commands independently.

In this case it a pipe from Mutt which passes the whole message body. I want to get grep, sed, delete and assign each of these to bash variables maybe.

Initially what I want is to be able to assign "message id" to a variable, "subject" to another variable etc Then pass those into proper commands arguments.

Here is how it will be

MessageBodyFromMutt|grep something -Ax -Bx |grep another thing from the original message| sed some stuff from the original message| cut from here to there

Obviously the above line does not do what I want.

I want all these commands to operate on the original message body. I hope it makes sense

  • Try tee. It forks your pipes (not to variables, though). – choroba May 29 '14 at 16:57
  • choraba, thanks. It seems like that is what I need but Mutt is not liking the parenthesis around the commands following tee. I tested some chains and they work in bash but Mutt pipe is complaining about such issues. Any recommendation? – yarun can May 30 '14 at 4:01
  • Mutt is probably running sh, not bash. Can you configure it to run bash? Or run bash -c '...'. – choroba May 30 '14 at 7:44
  • @choroba ok that is working. Here is what I am trying to do. So I have a command that is called "task add +sender emailbody +from" this is how I am trying to split up. "+"s are tags in taskwarrior. Do you feel like Tee can let me do that? I was thinking that I could assign them to shell vairbales but that does not seem to happen with tee. – yarun can May 31 '14 at 5:11
  • If you want to grep the original and sed the original.. Why don't you do multiple lines like cat original | grep<ENTER> cat original | sed <ENTER> e.t.c. It'd be clearer if you gave example of the data you start with and the data you want at the end via grep and sed. – barlop Jun 1 '14 at 18:21

You can save the output to a temporary file and use that file as the input for individual commands.
If the commands do not have output, you can use tee with bash process substitution; it would look like

MessageBodyFromMutt | tee >( command1 ) >( command2 ) >( command3 )

But since you have output, which would be mixed together, it does not help here - except if you change the commands to save the output to files.

If you cannot create a temporary file, you can save the output that you want to process multiple times in a variable, and then echo it multiple times:

messageBody="$( MessageBodyFromMutt )"
echo "$messageBody" | command1
echo "$messageBody" | command2
echo "$messageBody" | command3

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.