Bash-Skript zum Erkennen des Versionskontrollsystems durch Testen des Befehlsrückgabestatus


11

Ich arbeite an einem Bash-Skript, das ich für verschiedene Arten von VCS arbeiten möchte. Ich denke darüber nach zu testen, ob ein Verzeichnis ein Repo für ein System ist, indem ich einen typischen Info-Befehl ausführe und den Rückkehrcode, den Erfolg oder den Fehler überprüfe. Im Pseudocode:

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

Ich kann einen Befehl ausführen, z. B. darcs show repoverwenden $?, um seinen Rückkehrcode abzurufen.

Meine Frage ist: Gibt es eine gute Möglichkeit, die Rückkehrcode-Nummer in einer Zeile auszuführen und zurückzugeben? beispielsweise

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

Oder muss ich eine Funktion definieren?

Eine zusätzliche Anforderung ist, dass sowohl stderr als auch stdout gedruckt werden müssen.

Antworten:


15

Wenn der Rückkehrcode automatisch überprüft wird:

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

Sie können den Befehl auch ausführen und && (logisches UND) oder || verwenden (logisches ODER) danach, um zu überprüfen, ob es erfolgreich war oder nicht:

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

Umleiten stdoutund stderrkann einmal mit durchgeführt werdenexec

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"

Die ersten beiden execspeichern die Dateideskriptoren stdinund die stderrDateideskriptoren, die dritte leitet beide an /dev/null(oder an einen anderen Ort, wenn dies gewünscht wird). Die letzten beiden execstellen die Dateideskriptoren wieder her. Alles dazwischen wird ins Nirgendwo umgeleitet.

Fügen Sie andere Repo-Checks hinzu, wie von Gilles vorgeschlagen.


Schön und sauber, aber diese Methoden drucken Nachrichten an den Benutzer aus. Ich würde es vorziehen, wenn das Skript still ist (ich habe dies der Frage hinzugefügt).
Niall Murphy

2
Warum führen Sie diese in einer Subshell aus? Es ist unnötig.
Chris Down

4

Wie bereits erwähnt, wird if commandgeprüft, ob dies commanderfolgreich ist. In der Tat [ … ]ist ein gewöhnlicher Befehl, der außerhalb einer ifoder whileBedingung verwendet werden kann, obwohl es ungewöhnlich ist.

Für diese Anwendung würde ich jedoch die Existenz der charakteristischen Verzeichnisse testen. Dies ist in weiteren Randfällen korrekt. Bash / ksh / zsh / dash-Version (ungetestet):

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

Nun, es ist nicht sehr hübsch, aber es ist eine Möglichkeit, es inline zu machen:

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

Wenn Sie den Exit-Code eines Befehls testen, müssen Sie per Definition keinen expliziten Vergleich durchführen, es sei denn, Sie möchten mehr als Erfolg oder Misserfolg. Es gibt wahrscheinlich einen eleganteren Weg, dies zu tun.


0

Eine andere prägnante Option wäre:

[ -d .svn ] && { svn command 1; svn command 2; } 
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.