How to Display the Output of a Linux Command on Stdout and Also Pipe It to Another Command

How to show command output in stdout and also transfer it to pipe

ls |tee /dev/tty |grep dir

will do that, although it won't put a space between the two parts.

How to output bash command to stdout and pipe to another command at the same time?

Use tee:

ps -up `nvidia-smi |tee /dev/stderr |tail -n +16 | head -n -1 | sed 's/\s\s*/ /g' | cut -d' ' -f3` 

Since stdout is piped, you can't make a copy to it, so I picked stderr to show output.

If /dev/stderr is not available, use /proc/self/fd/2.

How to pipe stdout while keeping it on screen ? (and not to a output file)

Here is a solution that works at on any Unix / Linux implementation, assuming it cares to follow the POSIX standard. It works on some non Unix environments like cygwin too.

echo 'ee' | tee /dev/tty | foo

Reference: The Open Group Base Specifications Issue 7
IEEE Std 1003.1, 2013 Edition, §10.1:

/dev/tty

Associated with the process group of that process, if any. It is
useful for programs or shell procedures that wish to be sure of
writing messages to
or reading data from the terminal no matter how
output has been redirected.
It can also be used for applications that
demand the name of a file for output, when typed output is desired and
it is tiresome to find out what terminal is currently in use. In each process, a synonym for the controlling terminal

Some environments like Google Colab have been reported not to implement /dev/tty while still having their tty command returning a usable device. Here is a workaround:

tty=$(tty)
echo 'ee' | tee $tty | foo

or with an ancient Bourne shell:

tty=`tty`
echo 'ee' | tee $tty | foo

How to redirect output to a file and stdout

The command you want is named tee:

foo | tee output.file

For example, if you only care about stdout:

ls -a | tee output.file

If you want to include stderr, do:

program [arguments...] 2>&1 | tee outfile

2>&1 redirects channel 2 (stderr/standard error) into channel 1 (stdout/standard output), such that both is written as stdout. It is also directed to the given output file as of the tee command.

Furthermore, if you want to append to the log file, use tee -a as:

program [arguments...] 2>&1 | tee -a outfile

pipe output to stdout and then to command then to variable

Your code has a lot of dependencies. I will illustrate what I think that you need without using anything beyond standard unix tools.

This runs a command, seq 4, and sends all of its output to stdout and also sends all of its output to another command, sed 's/3/3-processed/', the output of which is captured in a variable, var:

$ exec 3>&1
$ var=$(seq 4 | tee >(cat >&3) | sed 's/3/3-processed/')
1
2
3
4

To illustrate that we successfully captured the output of the sed command:

$ echo "$var"
1
2
3-processed
4

Explanation: var=$(...) captures the output of file handle 1 (stdout) and assigns it to var. Thus, to make the output also appear on stdout, we need to duplicate stdout to another file handle before $(...) redirects it. Thus, we use exec to duplicate stdout as file handle 3. In this way, tee >(cat >&3) sends the output of the command both the original stdout (now called 3) and to file handle 1 which is passed on the the next stage in the pipeline.

So, using your toolchain, try:

exec 5>&1
dsym=$(xcodebuild -scheme "<myscheme>" archive | tee >(cat >&5) | php -r "$code")

writing screen output (stdErr) and output (stdOut) of a Linux command to separate files

Sounds like the additional output comes from stderr, which you can capture with 2>:

mycommand > outfile 2> stderr

How can I pipe output, from a command in an if statement, to a function?

The Print function doesn't read standard input so there's no point piping data to it. One possible way to do what you want with the current implementation of Print is:

if ! occ_output=$(sudo -u "$web_user" "$nextcloud_dir/occ" files:scan --all 2>&1); then
Print "Error: Failed to scan files. Are you in maintenance mode?"
fi

Print "'occ' output: $occ_output"

Since there is only one line in the body of the if statement you could use || instead:

occ_output=$(sudo -u "$web_user" "$nextcloud_dir/occ" files:scan --all 2>&1) \
|| Print "Error: Failed to scan files. Are you in maintenance mode?"

Print "'occ' output: $occ_output"

The 2>&1 causes both standard output and error output of occ to be captured to occ_output.

Note that the body of the Print function could be simplified to:

[[ $quiet_mode == No ]] && printf '%s\n' "$1"
(( logging )) && printf '%s\n' "$1" >> "$log_file"

See the accepted, and excellent, answer to Why is printf better than echo? for an explanation of why I replaced echo "$1" with printf '%s\n' "$1".



Related Topics



Leave a reply



Submit