Welcome to Stack Exchange! Lot's of good info here. Thank you for your due diligence first.
The issue I see with your command is that it is "Begging the Question." In other words, it assumes you know the answer before you even start.
Let's have a closer look:
cat file.txt
The contents of "file.txt" will go to STDOUT.
If the "cat" command generates any errors, they will do to STDERR.
AFTER the command completes, the exit code is set. 0 = success; anything else is an error.
The issue here is, you don't know if you should execute command1
or command2
until the output has already been sent. Which means, it's gone.
Compare that to this:
cat file.txt | sort
This is, effectively, 2 commands:
1: cat file.txt 1> temp_file
2: sort < temp_file
Ok not REAL Unix commands, done this way for clarification.
1: Send STDOUT to "tempfile" (that is the 1> part). Also send STDERR to the console.
2: Run the sort command, and read STDIN from "tempfile".
Putting the pipe |
between the two commands obviates the need for a temp file. The pipe means: Redirect STDOUT from "cat" to STDIN of "sort".
Your issue:
You want to redirect STDOUT the the STDIN of another command, but you do not yet know which command that is, so you cannot redirect it.
Before I get to a possible solution, let me give you a little background:
In Unix, there is a way to execute command the way you want to. To wit:
my_command argument1 argument2 && echo "Success" || echo "Failure"
After my_command
runs (and returns its exit status) with STDOUT & STDERR on the console, run one or the other of the echoes.
&&
means "Do this if the last command was successful"
||
means "Do this if the last command failed"
You are very close with your original command. You have:
cat file.txt | command1 || command2
Let's change that to this:
cat file.txt && command1 || command2
That gets you everything you want, except for the output.
Question 1:
If cat file.txt
works, then should command1
read STDOUT and ignore STDERR?
Likewise, if it fails, then should command2
read STDERR and ignore STDOUT?
Or, should either command read both STDOUT & STDERR?
I'll answer both questions for completeness.
Either way, you'll need a way to store the output for later processing. Normally a temp_file.
Capture STDOUT & STDERR in the same temp_file:
cat file.txt > /tmp/temp_file 2>&1
Capture STDOUT to temp_file#1 and STDERR to temp_file#2:
cat file.txt > /tmp/out_file 2 >/tmp/err_file
Question 2:
Do command1
and/or command2
allow for a file name on the command line?
command1 temp_file
Do command1
and/or command2
allow for a redirect from a file?
command2 < temp_file
Do command1
and/or command2
read STDIN?
cat temp_file | command1
Note: The Word Count command is an example.
wc temp_file
cat temp_file | wc
wc < temp_file
The second form may be problematic in the && || form. I include it here for completeness.
Ultimately, you will have to decide what command1
and command2
need to work.
We can now combine these together:
cat file.txt > /tmp/out_file 2>/tmp/err_file && command1 < /tmp/out_file || command2 < /tmp/err_file
Then delete the temp files:
rm /tmp/out_file /tmp/err_file
That should give you what you want.
I'm sure other guru's here can dream up a way of not using a temp_file. I like to keep thins simple and easily understandable because I am not in a programming shop and I have no idea who will have to maintain my code.
command1 <file.txt || command2 <file.txt
?comand1
do any reading before it fails?command1
reads from it before failing, whatever it read is gone, and cannot be re-read bycommand2
(unless you did something like store it in a temp file first).