5

I worte a bash script that have a few options turned on by switches from command line. I want to create option for the user to run this script in quiet mode which mean - all stdout will be redirected to /dev/null. i use a variable that is changed to /dev/null if the -q switch is on:

while getopts ":qhb:kape" opt; do
    case $opt in
       q)
        output=/dev/null
        ;;

and later i redirect acho mesagges to output:

echo "something" 1>>$output

My question is how to initilaize this var output above for case of no -q switch were sent. what is the value of standrd stdout destination (the text terminal that called the sctipt usually)?

thanks!

RD7
  • 628
  • 4
  • 9
  • 20

3 Answers3

8

You can use two methods...

Method 1

At the very beginning in your script set output variable to its default value. For example:

output=/dev/stdout

then, if -q switch has been used "overwrite" this default value by setting output=/dev/null.

This method implies that each instruction in your script will have its output redirected to ${output}.

Method 2

Use exec... At the very beginning in your script:

exec 6>&1 # saves stdout

Then, if -q option has been selected:

exec > /dev/null  # redirect stdout to /dev/null

And, finally...

exec 1>&6 6>&- # restore stdout

This way you don't have to explicitly redirect each command output...

mauro
  • 5,730
  • 2
  • 26
  • 25
0

Stdout file descriptor is &1

ie:

echo hello 1>&1

EDIT:

s=1
echo hello >& $s
xvan
  • 4,554
  • 1
  • 22
  • 37
  • i am trying to insert it into output variable, but the result is that nothing shown in the next command. i want that by default, if i don;t change this var when the user use -q, it will appear in the terminal echo "something" 1>>$output – RD7 Mar 15 '16 at 04:52
  • While this works with your example, it won't work with a _single_ variable for _both_ cases, as is the OP's intent (using variable `$output` to represent either stdout or `/dev/null`, depending on option `-q`); in order to use `>&`, you'd need a file _descriptor_ in _both_ cases, and there is no file descriptor for `/dev/null`. You could use _filenames_, however, as demonstrated in @mauro's answer. – mklement0 Mar 15 '16 at 05:43
  • Yup, you're right, you could open another fd like `exec 5>/dev/null`, but that's almost matching @mauro's answer. – xvan Mar 15 '16 at 05:54
0

You can redirect stdout as below.

while getopts ":qhb:kape" opt; do
    case $opt in
    q)
        old_stdout=`readlink -f /dev/stdout` # save old stdout value if required.
        exec 1>/dev/null # redirect stdout to /dev/null
        ;
    ....
    esac
done

echo hello world # It will not be printed on the screen
echo hello universe > $old_stdout # will be printed to original stdout (say terminal)

exec 1>$old_stdout #revert stdout to original value (say terminal)
anishsane
  • 20,270
  • 5
  • 40
  • 73
  • Good tip re `exec`, but `readlink -f` isn't portable; is there a reason not to use `/dev/stdout` directly? The most portable solution is to save the original stdout in a custom file descriptor, as in @mauro's answer. – mklement0 Mar 15 '16 at 05:16
  • 1
    We cannot use `/dev/stdout`, because that will also point to `/dev/null`... `lrwxrwxrwx 1 root root 15 Mar 1 15:36 /dev/stdout -> /proc/self/fd/1` – anishsane Mar 15 '16 at 07:09
  • 1
    But yes, using a separate file descriptor is a much better way. – anishsane Mar 15 '16 at 07:09
  • Thanks for the explanation; I see that Linux behaves that way; on OSX, `/dev/stdout` actually keeps pointing to `/dev/fd/1`, even while redirected. – mklement0 Mar 15 '16 at 07:42
  • Where does `/dev/fd/1` point to? Is there any `readlink -f` like utility there? Anyone from [this](http://unix.derkeiler.com/Newsgroups/comp.unix.shell/2011-12/msg00113.html) link working? On linux, `/dev/fd/1` points to terminal by default & to `/dev/null` when redirected... – anishsane Mar 15 '16 at 07:51
  • `/dev/fd/1` is not a symlink on OSX - it is the actual character special file. `readlink` exists, but not with `-f`, so you don't get an absolute path, and you don't get recursive resolution; GNU readlink can be installed via HomeBrew. A POSIX-compliant implementation of `readlink -f` can be found in [this answer](http://stackoverflow.com/a/29835459/45375) of mine. – mklement0 Mar 15 '16 at 07:55