20

How would one implement a dry-run option in a bash script?

I can think of either wrapping every single command in an if and echoing out the command instead of running it if the script is running with dry-run.

Another way would be to define a function and then passing each command call through that function.

Something like:

function _run () {
    if [[ "$DRY_RUN" ]]; then
        echo $@
    else
        $@
    fi
}

`_run mv /tmp/file /tmp/file2`

`DRY_RUN=true _run mv /tmp/file /tmp/file2`

Is this just wrong and there is a much better way of doing it?

4
  • So, you want to print what the command will do (including the values of the $VARIABLES) without actually executing the command. I use something like your _run() function, sometimes with 'set -xv', but I would love a better way. Jun 2, 2010 at 22:46
  • yeah, exactly that. I'm wondering if there isn't an internal variable you can set in bash so commands don't actually execute, instead of passing them through a function Jun 2, 2010 at 22:48
  • 2
    There's no reason that this question should have been marked community wiki. Jun 2, 2010 at 23:36
  • Bash is a shell. There is no reason for it to do dry runs. I don't think there is a better way of doing it than you've already done.
    – d-_-b
    Jun 3, 2010 at 0:31

2 Answers 2

2

See BashFAQ/050: I'm trying to put a command in a variable, but the complex cases always fail! for a discussion of this subject.

Although now removed, the section How to add testing capability to a programs may still be useful.

3
  • Not an alternative, but it looks like an excellent resource for testing and working with longer bash programs. Jun 3, 2010 at 8:03
  • I rolled back the edit that added an anchor to a particular part of the linked page since the point of my answer, as stated, is to read the discussion as a whole rather than point to one specific how-to portion. The point of the linked page is generally to try to avoid putting commands to be executed into variables since there are a lot of gotchas. Jun 3, 2010 at 9:34
  • It would be far more useful if this answer summarised the salient points of this article. One line answers are still poor answers.
    – Mark Booth
    Nov 3, 2015 at 10:53
5

I wanted to play with the answer from @Dennis Williamson's. Here's what I got:

Run () {
    if [ "$TEST" ]; then
        echo "$*"
        return 0
    fi

    eval "$@"
}

The eval "$@" is important here, and is better then simply doing $*. $@ returns all parameters and $* returns all parameters with no whitespace/quoting.

$ mkdir dir
$ touch dir/file1 dir/file2
$ FOO="dir/*"
$ TEST=true Run ls -l $FOO
ls -l dir/file1 dir/file2
$ Run ls -l $FOO
-rw-r--r--  1 stefanl  stefanl  0 Jun  2 21:06 dir/file1
-rw-r--r--  1 stefanl  stefanl  0 Jun  2 21:06 dir/file2

Your Answer

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

Not the answer you're looking for? Browse other questions tagged or ask your own question.