0

I have a user-provided bash script that creates a directory in some way and outputs its path. It can work in many ways, for example, it can clone a git repository, do some setting up, and then output the path. Something like this:

git clone ...repo --quiet && echo "...path"

I run it using command substitution, wrapping with $(...) and using the resulting path. Something like this:

path=$(...)

The command itself is user-provided, so it can be anything, I can't anticipate it will always be git clone.

It works well, but if the commands before the final echo outputs anything, it will mess up the result. I could redirect stdout to stderr for all preceding commands and only use stdout at the last step, but I feel it's a hack.

Is there any way to leave stdout and stderr to the caller's stdout and stderr, but have a separate stream for the result?

Kamil Maciorowski
  • 69,815
  • 22
  • 136
  • 202

1 Answers1

3

This will save the last line of output:

path=$(whatever | tail -n 1)

If you need all the output to be utilized in some way:

  • use tee to print the output to the tty

    path=$(whatever | tee /dev/tty | tail -n 1)
    
  • or to save it

    path=$(whatever | tee ./file | tail -n 1)
    
  • or to process it (and print to the tty or a file, not to stdout which feeds the variable)

    path=$(whatever | tee >(grep foo | wc -c >/dev/tty) | tail -n 1)
    
  • You can even send (fork) the output to many destinations:

    path=$(whatever | tee /dev/tty ./file /some/named/fifo >(tool1) | tail -n 1)
    

Obviously a newline within the echoed path will break the solution.


If you can modify the final echo command in the user-provided script then please see this answer of mine for an approach that uses temporary files.

Kamil Maciorowski
  • 69,815
  • 22
  • 136
  • 202
  • It works if I want it to go to the terminal, but what if the stdout is redirected somewhere? I have a test.sh: ```path=$((echo "doing something..." && echo "path") | tee /dev/tty | tail -1) && echo $path > result``` If I call it with ```./test.sh > log.txt```, it still outputs to the terminal. Is there any way to support this? I'd like to have both lines in the log.txt, and only the "path" in the result. – Tamás Sallai Dec 13 '18 at 11:58
  • Thank you, that link was a good guidance, I decided to go on the tempfile approach. This is the script I came up with: ```function dosth () { echo "doing something..."; echo "path" >$1; }; result_tmp=$(mktemp); trap 'rm $result_tmp' EXIT; dosth $result_tmp; path=$(cat $result_tmp); echo path > result``` – Tamás Sallai Dec 13 '18 at 14:08