7

I am working on a bash script where I need to conditionally execute some things if a particular file exists. This is happening multiple times, so I abstracted the following function:

function conditional-do {
    if [ -f $1 ]
    then
        echo "Doing stuff"
        $2
    else
        echo "File doesn't exist!"
    end
}

Now, when I want to execute this, I do something like:

function exec-stuff {
    echo "do some command"
    echo "do another command"
}
conditional-do /path/to/file exec-stuff

The problem is, I am bothered that I am defining 2 things: the function of a group of commands to execute, and then invoking my first function.

I would like to pass this block of commands (often 2 or more) directly to "conditional-do" in a clean manner, but I have no idea how this is doable (or if it is even possible)... does anyone have any ideas?

Note, I need it to be a readable solution... otherwise I would rather stick with what I have.

3 Answers 3

7

This should be readable to most C programmers:

function file_exists {
  if ( [ -e $1 ] ) then 
    echo "Doing stuff"
  else
    echo "File $1 doesn't exist" 
    false
  fi
}

file_exists filename && (
  echo "Do your stuff..."
)

or the one-liner

file_exists filename && echo "Do your stuff..."

Now, if you really want the code to be run from the function, this is how you can do that:

function file_exists {
  if ( [ -e $1 ] ) then 
    echo "Doing stuff"
    shift
    $*
  else
    echo "File $1 doesn't exist" 
    false
  fi
}

file_exists filename echo "Do your stuff..."

I don't like that solution though, because you will eventually end up doing escaping of the command string.

EDIT: Changed "eval $*" to $ *. Eval is not required, actually. As is common with bash scripts, it was written when I had had a couple of beers ;-)

Sign up to request clarification or add additional context in comments.

4 Comments

That won't work, I have output to the user indicating whether or not it was done, which I want to keep... the point of the function was to get rid of all that boilerplate if, going back to inlining it would bloat the script again beyond what I want.
The function I wrote is actually different a bit (I changed it above), but I do stuff in both the if and the else condition (which I abstracted out)... Also, the audience is not sysadmins/bash scripters... it's programmers who would be comfortable with functions.
I think I understand what you need now. This is actually what many of my scripts look like. Updated it again :-)
Added a "true" one-liner version that will evaluate the code from inside of the function. Ever heard of "bash-coma"? It's the condition that occurs after intense scripting sessions, when you start believing every problem could be solved with a good bash-script. Girlfriend grumpy? I can fix that. :-)
0

One (possibly-hack) solution is to store the separate functions as separate scripts altogether.

1 Comment

Sorry, the functions are all waaaaay too small for that, and I'm trying to merge it to 1 line so all needed to invoke is in the same place.
0

The cannonical answer:

[ -f $filename ] && echo "it has worked!"

or you can wrap it up if you really want to:

function file-exists {
    [ "$1" ] && [ -f $1 ]
}

file-exists $filename && echo "It has worked"

Comments

Your Answer

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

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.