Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems. Join them; it only takes a minute:

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

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
    something else

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.

share|improve this question
up vote 14 down vote accepted

If automatically checks the return code:

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

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
elif (test -d .git); then

# 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.

share|improve this answer
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). – Niall Murphy Dec 13 '10 at 18:55
Why are you running these in a subshell? It's unnecessary. – Chris Down Dec 3 '11 at 16:09

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):

if [ -d .svn ]; then
elif [ -d CVS ]; then
  while ! [ "$d" -ef / ]; do
    if [ -d "$d/.bzr" ]; then
    elif [ -d "$d/_darcs" ]; then
    elif [ -d "$d/.git" ]; then
    elif [ -d "$d/.hg" ]; then
    if [ -n "$vc" ]; then break; fi
if [ -z "$vc" ]; then
  echo 1>&2 "This directory does not seem to be under version control."
  exit 2

In POSIX sh, there is no -ef (same file) construct, so a different test is needed to break out of the recursion when the root directory is reached. Replace while ! [ "$d" -ef / ]; by while [ "$(cd -- "$d"; command pwd)" != / ];. (Use command pwd and not pwd because some shells track symbolic links in pwd and we don't want that here.)

share|improve this answer

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|improve this answer

Another succinct option would be:

[ -d .svn ] && { svn command 1; svn command 2; } 
share|improve this answer

Your Answer


By posting your answer, you agree to the privacy policy and terms of service.

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