For simplicity I would like to do:

echo cart | assign spo;
echo $spo  

Output: cart

Does such an assign application exist?

I am aware of all the ways to do this using substitution.

  • Why do you want to do this without substitution?
    – Thanatos
    Nov 8, 2013 at 19:08
  • I like the reverse Polish notation flow when writing with pipes only. I am much faster coding and the codes quality / speed is not so important. Also I don't when chaining it is hella easier to comment out parts of the chain and echo the current output rather then erase ticks etc. Nov 8, 2013 at 19:51
  • If you're concerned about ease of debugging, consider putting the backticks command on a series of separate lines. A=$( some | command | here ) with each of some |, command |, and here on its own line. Jan 26, 2015 at 22:59

6 Answers 6


You could do something like this, if you use bash:

echo cart | while read spo; do echo $spo; done

Unfortunately, variable "spo" won't exist outside of the while-do-done loop. If you can get what you want done inside the while-loop, that will work.

You can actually do almost exactly what you wrote above in ATT ksh (not in pdksh or mksh) or in the fabulous zsh:

% echo cart | read spo
% echo $spo

So, another solution would be to use ksh or zsh.

  • 1
    You can use coprocesses in the Korn Shell (e.g. mksh): echo cart |& while read -p spo; do echo $spo; done (actually better to use while IFS= read -p -r spo; do… though)
    – mirabilos
    Feb 27, 2014 at 14:03
echo cart | { IFS= read -r spo; printf '%s\n' "$spo"; }

Would work (store the output of echo without the trailing newline character into the spo variable) as long as echo outputs only one line.

You could always do:

assign() {
  eval "$1=\$(cat; echo .); $1=\${$1%.}"
assign spo < <(echo cart)

The following solutions would work in bash scripts, but not at the bash prompt:

shopt -s lastpipe
echo cat | assign spo


shopt -s lastpipe
whatever | IFS= read -rd '' spo

To store the output of whatever up to the first NUL characters (bash variables can't store NUL characters anyway) in $spo.


shopt -s lastpipe
whatever | readarray -t spo

to store the output of whatever in the $spo array (one line per array element).

  • 1
    shouldn't there be a space between IFS= and read?
    – caesarsol
    Apr 23, 2015 at 13:36
  • All hail last pipe . Also side note set +m ( ermmm or -m ) is needed from a command line she'll as last pipe does not work with job control active . Oct 2, 2015 at 3:43

If I understand the issue correctly you want to pipe stdout to a variable. At least that was what I was looking for and ended up here. So for those who share my fate:

spa=$(echo cart)

Assigns cart to the variable $spa.

  • 2
    That's what they call substitution, which the OP wanted to avoid. Sep 30, 2015 at 20:20
  • This was useful to me, i just needed to assign it to a variable, i didn't care how it got there! Apr 24, 2019 at 19:37
  • The shell does indeed pipe the output of the command to the variable. It ALSO pipes stdin into the command. This can mess up while loops that read input, and cause them to exhaust stdin and quit reading after one loop. This is a baffling situation -- no error occurs and no indication of what is the matter is exported. You must explicitly redirect stdin from /dev/null to prevent the loop from stopping at one iteration. out=$( prog </dev/null arg1 arg2 ...) # does the trick. Just putting this here to be stumbled upon someday and make someone's day.
    – Chris Reid
    Jan 4, 2020 at 6:30

If you just want to output the current pipe stream use cat.

echo cart | cat 

If you want to continue your command chain, try using the tee command to echo the output.

echo cart | tee /dev/tty | xargs ls

You could use an alias to shorten the command.

alias tout='tee /dev/tty'
echo cart | tout | xargs ls
  • Why would you want to pipe output to a plain cat? Jan 26, 2015 at 22:57
  • 1
    @roaima Some command recognize they are running on a terminal an behave differently than if they are outputting to a pipe. In particular they may truncate lines to the current screen width. For most command the cat command is redundant.
    – BillThor
    Jan 27, 2015 at 0:32
  • Ah ok, I see now what you were trying to illustrate. The echo | cat construct threw me. Jan 27, 2015 at 0:35

Here's my solution to the problem.

# assign will take last line of stdout and create an environment variable from it
# notes: a.) we avoid functions so that we can write to the current environment
#        b.) aliases don't take arguments, but we write this so that the "argument" appears
#            behind the alias, making it appear as though it is taking one, which in turn
#            becomes an actual argument into the temporary script T2.
# example: echo hello world | assign x && echo %x outputs "hello world"
alias assign="tail -1|tee _T1>/dev/null&&printf \"export \\\$1=\$(cat _T1)\nrm _T*\">_T2&&. _T2"

If you are willing to use a temporary file you can avoid substitution and the expensive pipe.

echo cart > tmp.$$; read spo < tmp.$$; rm tmp.$$

Fun shell fact: you can even move the redirection operator to the front for improved "pipe" feeling:

echo cart > tmp.$$; < tmp.$$ read spo

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .