2

I have many commands in a bash script that have >/dev/null 2>&1 used to redirect stdout and stderr to /dev/null.

Let us say I have a variable called echoOn, which can be either 0 or 1.

If echoOn is equal to 0, then I wish to keep the redirections on the commands in the script. If it is equal to 1, then I do not want the redirection in place, so the commands are able to output.

I do not wish to suppress the output of all commands but only specific ones within the script.

Is there a more abstract way for me to do this without manually adding if statements to every command in question?

I am open to having a function in which I pass the command and its arguments and replacing each command with a call to the aforementioned function and the command to be executed.

3
  • A not very abstracted way: case "$echoOn" in 0) exec {myout}>/dev/null {myerr}>&$myout ;; 1) exec {myout}>&1 {myerr}>&2 ;; esac ; echo stuff 1>&$myout 2>&$myerr Commented Feb 7, 2020 at 4:14
  • 1
    Why not just create a variable that's set to /dev/null when you want to suppress output and to /dev/stdout when you don't? Commented Feb 7, 2020 at 16:38
  • @ruakh That is another viable option I had not thought of. Though, I would create two variables: one for stdout and one for stderr. Commented Feb 8, 2020 at 19:41

2 Answers 2

3

I'm not sure if I'm understanding your requiremens correctly, but how about:

# put the lines below at the beginning of the script
if (( echoOn == 0 )); then
    exec 3>/dev/null 2>&3
else
    exec 3>&1
fi

# then execute your commands
echo foo >&3    # a command which wants to switch the redirection
echo warn >&2   # simulates an error
echo bar        # a command which does not need the switch

If echoOn is set to 0, only bar is displayed on the terminal.

The problem is that you need to modify your code replacing all >/dev/null 2>&1 expressions with >&3.

[Update]

In order to controll both stdout and stderr on the specific command, please try the following:

echoOn=0        # set to "1" to ebable stdout/stderr else set to "0"
if (( echoOn == 0 )); then
    exec 3>/dev/null
    exec 4>/dev/null
else
    exec 3>&1
    exec 4>&2
fi

echo foo 1>&3 2>&4          # a command which wants to switch the redirection
(echo warn >&2) 1>&3 2>&4   # simulates an error
echo bar                    # a command which does not need the switch
(echo error >&2)            # simulates anerror

Please put 1>&3 2>&4 to the commands you want to control its output

Sign up to request clarification or add additional context in comments.

12 Comments

This is exactly what I was looking for. Thank you!
What if I wanted echo warn >&2 to also display?
Sorry for my misunderstanding. I've updated my answer. I hope this is what you want.
Thank you for the feedback. It's good both of us had a better understanding to each other thru the discussion. Sorry for bothering you many times anyway. BR.
As this is bash, if you use something like {myerr}>/dev/null and 2>&$myerr instead of 4>/dev/null and 2>&4 then (a) you get a friendly name to help remember what the fd is for, and (b) there is less chance that the fd is already in use somewhere else in the code
|
1

Try this:

if [ $# -ge 1 -a $1 -eq 0 ]; then
    exec 3>/dev/null 1>&3 2>&3
else
    exec 3>&1
fi

foo="hello"
warn="world"
bar="stackoverflow"


# then execute your commands
echo $foo >&3    # a command which wants to switch the redirection
echo $warn >&2   # simulates an error
echo $bar        # a command which does not need the switch

I have many commands in a bash script that have >/dev/null 2>&1 used to redirect stdout and stderr to /dev/null.

The accepted answer doesn't use $ to get the value of your variable. I think you might get errors if you try to run the script. And you need to redirect both stdout and stderr. So my script redirect both to /dev/null if you pass an argument 0 to the script, otherwise it doesn't redirect.

No Output if you run ./example.sh 0

Output ./example 1

hello
world
stackoverflow

3 Comments

In (( echoOn == 0 )) , the $ is optional because of the arithmetic context.
How about echo foo?
This is not an arithmetic context and the $ is necessary. You have to write echo $foo. In echo $(( foo + bar )) the Dollars are unneeded.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.