DmitrySemenov
DmitrySemenov

Reputation: 10365

zsh conditional OR fails

# delete git branch
git--() {

  BRANCH=$1

  if [ -n $BRANCH]; then
    BRANCH=$(git rev-parse --abbrev-ref HEAD)
  fi

  if [ "$BRANCH" = 'master' || "$BRANCH" = 'develop' ]; then

    red "You should not delete $BRANCH"
    return 0
  fi
}

fails with

git--:[:8: ']' expected
zsh: master: command not found...
git--:8: command not found: master
No branch specified therefore I'm using the current one: master
On branch master
nothing to commit, working tree clean
Do you really want to delete the branch master (y/n)?

however if I change

if [ "$BRANCH" = 'master' || "$BRANCH" = 'develop' ]; then

to

if [ "$BRANCH" = 'master' ]; then

eveything works. How can I do OR comparison?

thanks!

Upvotes: 4

Views: 10862

Answers (2)

Calvin Taylor
Calvin Taylor

Reputation: 694

You should run your shell script in debug mode, eg 'zsh -x', it'll spit out what variables are at each step so you have a good understanding of what's happening.

The BRANCH variable is being clobbered here; The -n checks to see if BRANCH has a value and if so updates it. I expect you meant to use the -z switch;

  if [ -n $BRANCH]; then
    BRANCH=$(git rev-parse --abbrev-ref HEAD)
  fi

I think your script should look more like

git--() {
  BRANCH=$1

  if [ -z "$BRANCH" ] ; then
    BRANCH=$(git rev-parse --abbrev-ref HEAD)
  fi
  if [ -z "$BRANCH" ] ; then
    if [ "$BRANCH" = 'master' ] || [ "$BRANCH" = 'develop' ] ; then
      red "You should not delete $BRANCH"
      return 0
    else
      git branch $BRANCH -D  || ( red "Could not delete $BRANCH" && return 1 )
    fi
  else
    red "branch not understood"
    return 1
  fi
}

Upvotes: 1

Adaephon
Adaephon

Reputation: 18429

You have two primary options (of course there are also some less straight forward ones)

  1. Use zsh syntax and use [[ ... ]] instead of [ ... ].

    if [[ "$BRANCH" = 'master' || "$BRANCH" = 'develop' ]]; then
    
  2. Use -o instead of || in order to stay POSIX compliant

    if [ "$BRANCH" = 'master' -o "$BRANCH" = 'develop' ]; then
    

If the code is only ever to be run with zsh, I would recommend to go with 1.


The reason for the error message is that [ is only a regular command and not part of the zsh syntax. [ expects ] as last parameter, but || is part of the zsh syntax and has priority. It acts as a separator between commands and splits the "condition" into two commands

[ "$BRANCH = 'master'

and

"$BRANCH" = 'develop' ]

The second command is run, if the first one fails.

Running the first command fails, as the the closing ] is missing. This leads to the error message:

git--:[:8: ']' expected

For the second command "$BRANCH" is substituted by the value master. As there is no command named master this returns the error message

zsh: master: command not found...

Upvotes: 12

Related Questions