Bash script to detect the version control system by testing command return status

14,727

Solution 1

If automatically checks the return code:

if (darcs show repo); then
  echo "repo exists"
else
  echo "repo does not exist"
fi

You could also run the command and use && (logical AND) or || (logical OR) afterwards to check if it succeeded or not:

darcs show repo && echo "repo exists"
darcs show repo || echo "repo does not exist"

Redirecting stdout and stderr can be done once with exec

exec 6>&1
exec 7>&2
exec >/dev/null 2>&1

if (darcs show repo); then
  repo="darcs"
elif (test -d .git); then
  repo="git"
fi

# The user won't see this
echo "You can't see my $repo"

exec 1>&6 6>&-
exec 2>&7 7>&-

# The user will see this
echo "You have $repo installed"

The first two exec are saving the stdin and stderr file descriptors, the third redirects both to /dev/null (or somewhere other if wished). The last two exec restore the file descriptors again. Everything in between gets redirected to nowhere.

Append other repo checks like Gilles suggested.

Solution 2

As others have already mentioned, if command tests whether command succeeds. In fact [ … ] is an ordinary command, which can be used outside of an if or while conditional although it's uncommon.

However, for this application, I would test the existence of the characteristic directories. This will be correct in more edge cases. Bash/ksh/zsh/dash version (untested):

vc=
if [ -d .svn ]; then
  vc=svn
elif [ -d CVS ]; then
  vc=cvs
else
  d=$(pwd -P)
  while [ -n "$d" ]; do
    if [ -d "$d/.bzr" ]; then
      vc=bzr
    elif [ -d "$d/_darcs" ]; then
      vc=darcs
    elif [ -d "$d/.git" ]; then
      vc=git
    elif [ -d "$d/.hg" ]; then
      vc=hg
    fi
    if [ -n "$vc" ]; then break; fi
    d=${d%/*}
  done
fi
if [ -z "$vc" ]; then
  echo 1>&2 "This directory does not seem to be under version control."
  exit 2
fi

Solution 3

Well, it's not very pretty, but it's one way to do it inline:

if darcs show repo > /dev/null 2>&1; then <do something>; fi

By definition, if tests the exit code of a command, so you don't need to do an explicit comparison, unless you want more than success or failure. There's probably a more elegant way to do this.

Share:
14,727

Related videos on Youtube

Niall Murphy
Author by

Niall Murphy

Postdoc. Interested in TCS, natural computing, synthetic biology.

Updated on September 17, 2022

Comments

  • Niall Murphy
    Niall Murphy almost 2 years

    I am working on a bash script that I would like to work for several types of VCS. I am thinking of testing if a directory is a repo for a system by running a typical info command and checking the return code, success or error. In pseudo code:

    if a svn command succeded;
        Then run svn commands
    elif a darcs command succeded;
        Then run darcs commands
    elif a mercurial command succeded;
        then run hg commands
    else 
        something else
    fi
    

    I can run a command, e.g. darcs show repo and use $? to get its return code.

    My question is: is there a neat way to run and return the return code number in one line? for example

    if [ 0 -eq `darcs show repo`$? ]; 
    

    Or do I have to define a function?

    An added requirement is that both stderr and stdout should be printed.

  • Niall Murphy
    Niall Murphy over 13 years
    Nice and clean, however these methods print out messages to the user. I would prefer the script to be silent (I have added this to the question).
  • clerksx
    clerksx over 12 years
    Why are you running these in a subshell? It's unnecessary.