Skip to main content
traverse parent directories using physical pwd to avoid worrying about symlinks
Source Link
Gilles 'SO- stop being evil'
  • 865.3k
  • 205
  • 1.8k
  • 2.3k

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=. # Start with current directory
  while ! [ "$d" -ef / ]; 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

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

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

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=. # Start with current directory
  while ! [ "$d" -ef / ]; 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

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

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
Starting with d=.. results in 'not under version control' if run from the root of the repository
Source Link

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=.. # Start with current directory
  while ! [ "$d" -ef / ]; 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

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

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=..
  while ! [ "$d" -ef / ]; 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

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

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=. # Start with current directory
  while ! [ "$d" -ef / ]; 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

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

Source Link
Gilles 'SO- stop being evil'
  • 865.3k
  • 205
  • 1.8k
  • 2.3k

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=..
  while ! [ "$d" -ef / ]; 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

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