20

I have a script. I would like to give this script a quiet mode and a verbose mode.

This is the equivalent of:

if $verbose
then
  redirect="> /dev/null"
fi

echo "Verbose mode enabled" $redirect # This doesn't work because the redirect isn't evaluated.

I'd really like a better way of doing this than writing if-elses for every statement affected.

eval could work, but has obvious side effects on other variables.

Redwood
  • 66,744
  • 41
  • 126
  • 187

4 Answers4

15

You could write a wrapper function:

redirect_cmd() {
    # write your test however you want; this just tests if SILENT is non-empty
    if [ -n "$SILENT" ]; then
        "$@" > /dev/null
    else
        "$@"
    fi
}

You can then use it to run any command with the redirect:

redirect_cmd echo "unsilenced echo"
redirect_cmd ls -d foo*

SILENT=1
redirect_cmd echo "nothing will be printed"
redirect_cmd touch but_the_command_is_still_run

(If all you need to do is echo with this, you can of course make the function simpler, just echoing the first argument instead of running them all as a command)

thanasisp
  • 5,855
  • 3
  • 14
  • 31
Cascabel
  • 479,068
  • 72
  • 370
  • 318
  • I like this solution. `echo` was just an example. I could have picked a better one. – Redwood Mar 26 '10 at 00:24
  • @Vlad: Oops. I don't know what happened to my usual obsessive quoting there. Edited! – Cascabel Mar 26 '10 at 05:52
  • This answer works great.. BUT i found a usage scenario that fails: redirect_cmd CC=gcc CFLAGS="-O2 -g0" ./configure ${SQLITE_CONFIGURE_OPT} --prefix=${CURR_DIR}/${INSTALL_DIR} I get the error utils/util-optout.sh: line 33: CC=gcc: command not found.. any clue??? – Heston T. Holtmann Jul 08 '13 at 17:58
  • A more simple example of what works and doesn't with this solution; this fails: redirect_cmd CC=g++ make all; .... but it works if you move the CC=g++ option at the end as in: redirect_cmd make all CC=g++; – Heston T. Holtmann Jul 08 '13 at 19:15
  • `redirect_cmd` should `return $?` because `redirect_cmd some_action && echo 'success' || echo 'failure'` – cprn Apr 26 '16 at 16:08
9

Got the idea from another question:

#!/bin/sh

if [ $SILENT ]; then
    exec &>/dev/null
fi

echo "Silence here."
Community
  • 1
  • 1
jholster
  • 5,066
  • 1
  • 27
  • 20
5

Not perfect, but how about setting redirect to either "/dev/null" or "/dev/tty", and then doing

{
   echo "verbose"
    ....
} > $redirect
Paul Tomblin
  • 179,021
  • 58
  • 319
  • 408
1

Consider whether it would be worth setting set -x for detailed logging to stderr in verbose mode. If that's so, then verbose-only output can be achieved with a no-op : like this.

while getopts "v" o
do case "$o" in
   v) set -x;;
   esac
done

echo "This will always be output"           # goes to stdout
: this will only be output in verbose mode  # goes to stderr

: evaluates it's arguments but does nothing with them. set -x will show what was evaluated on stderr as each statement is executed.

It also lets you split verbose and standard logs by stream.

Might not be what you need here, but it can be a handy trick.

Paul Hodges
  • 13,382
  • 1
  • 17
  • 36