0

I wrote some BASH code that executes a lot of external commands (causing side effects). So for developing and debugging I thought I wrap the executions in a shell function, so that the commands will either be executed or printed.

So that basic code is:

run()
{
    if [ "$print_commands" -ne 0 ]; then
        echo "$@"
    else
        "$@"
    fi
}

Unfortunately most of the external commands output something when successful (like "success"), so I had been using > /dev/null to redirect such output. However there are some status queries that do output the status, and that cannot be discarded.

So obviously I cannot add > /dev/null inside run; also I don't want to add a second function that redirects, duplicating most code.

I tried a solution like this:

silence='>/dev/null'
run some_command with params $silence

The idea was to set silence to the empty string when just printing the commands, which works, but when executing the commands I get:

error: unrecognized arguments: >/dev/null

Is there some half-way elegant solution without using eval?

U. Windl
  • 1,411

2 Answers2

1

Why not check another variable in the run function use it to determine redirection?

run()
{
    if [ "$print_commands" -ne 0 ]; then
        echo "$@"
    elif [ "$silence" -ne 0 ]; then
        "$@" > /dev/null
    else
        "$@"
    fi
}

Then:

silence=1 run some_command with params whose output is not needed
silence=0 run some_command with params whose output is needed

Or you could output the command to stderr instead of stdout:

run()
{
    if [ "$print_commands" -ne 0 ]; then
        echo "$@" >&2
    else
        "$@"
    fi
}
muru
  • 72,889
  • I wasn't aware that the syntax "var=val cmd ..." can be used for shell functions, too; I thought it's only available for external commands. Redirecting to stderr is not an option as there could be real error messages and I intend to paste the output to a terminal for execution (or into another script). See also the related question https://unix.stackexchange.com/q/726124/320598 – U. Windl Nov 24 '22 at 09:02
  • @U.Windl the more I look at this, the more it feels like you're reinventing set -n – muru Nov 24 '22 at 09:03
  • You should be a bit more verbose on set -n (how to use it here?). – U. Windl Nov 24 '22 at 09:20
  • @U.Windl to me it looks you have some script or something in which you prefix the commands with this run function. Instead of that, run the script with bash -n, or run set -n conditionally at the top of the script. – muru Nov 24 '22 at 09:38
  • Sorry, but when using bash -n my_script, then nothing is being executed, so nothing is being output. I don't see the usefulness of set -n still... – U. Windl Nov 24 '22 at 10:31
  • @U.Windl ah, sorry, it should be both -n and -v, so bash -nv. – muru Nov 24 '22 at 10:34
  • Still that does not help: It outputs the lines of my script, but not what the script would execute. Maybe my description of the problem was not good. – U. Windl Nov 24 '22 at 12:12
0

Based on https://unix.stackexchange.com/a/726123/320598 I decided to add an additional first parameter to run to control redirection to /dev/null:

run()
{
    declare silence="$1"; shift
    if [ "$print_commands" -ne 0 ]; then
        echo "$@"
    elif [ "$silence" -ne 0 ]; then
        "$@" > /dev/null
    else
        "$@"
    fi
}

run 0 non_redirected_command params run 1 redirected_command params

U. Windl
  • 1,411