Скрипт Bash для обнаружения системы контроля версий путем тестирования статуса возврата команды

11

Я работаю над сценарием Bash, который я хотел бы работать для нескольких типов VCS. Я подумываю проверить, является ли каталог репозиторием для системы, выполнив типичную команду info и проверив код возврата, успех или ошибку. В псевдокоде:

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

Я могу запустить команду, например, darcs show repoи использовать, $?чтобы получить код возврата.

У меня вопрос: есть ли удобный способ запустить и вернуть код возврата в одной строке? например

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

Или я должен определить функцию?

Дополнительным требованием является печать как stderr, так и stdout.

Найл Мерфи
источник

Ответы:

15

Если автоматически проверяет код возврата:

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

Вы также можете запустить команду и использовать && (логическое И) или || (логическое ИЛИ) после этого, чтобы проверить, успешно это или нет:

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

Перенаправление stdoutи stderrможет быть сделано один раз с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"

Первые два execсохраняют дескрипторы файлов stdinи stderr, третий перенаправляет их /dev/null(или куда-то еще, если это необходимо). Последние два execвосстанавливают файловые дескрипторы снова. Все между ними перенаправляется в никуда.

Добавьте другие проверки репо, как предложил Жиль.

шутник
источник
Красиво и чисто, однако эти методы выводят сообщения пользователю. Я бы предпочел, чтобы сценарий был тихим (я добавил это к вопросу).
Найл Мерфи
2
Почему вы запускаете их в подоболочке? Это не нужно.
Крис Даун
4

Как уже упоминали другие, if commandпроверяет, commandудастся ли . На самом деле [ … ]это обычная команда, которая может быть использована вне ifили whileусловно, хотя это редко встречается.

Однако для этого приложения я бы проверил наличие характерных каталогов. Это будет правильно в более сложных случаях. Версия bash / ksh / zsh / dash (не проверена):

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
Жиль "ТАК - перестань быть злым"
источник
2

Ну, это не очень красиво, но это один из способов сделать это встроенным:

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

По определению, если тестирует код завершения команды, вам не нужно делать явное сравнение, если только вы не хотите большего, чем успех или неудача. Вероятно, есть более элегантный способ сделать это.

SethG
источник
0

Другой краткий вариант будет:

[ -d .svn ] && { svn command 1; svn command 2; } 
Михай Ротару
источник