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 $@

`_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?

  • 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. – Stefan Lasiewski Jun 2 '10 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 – Andrei Serdeliuc Jun 2 '10 at 22:48
  • 2
    There's no reason that this question should have been marked community wiki. – Paused until further notice. Jun 2 '10 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 '10 at 0:31

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.

  • Not an alternative, but it looks like an excellent resource for testing and working with longer bash programs. – Andrei Serdeliuc Jun 3 '10 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. – Paused until further notice. Jun 3 '10 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 '15 at 10:53

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

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

    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, privacy policy and cookie policy

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