wake-up-neo.net

Ermitteln Sie, ob der Pfad des Benutzers ein bestimmtes Verzeichnis enthält

Wie würde ich mit /bin/bash feststellen, ob ein Benutzer ein bestimmtes Verzeichnis in seiner $ PATH-Variablen hat?

Zum Beispiel

if [ -p "$HOME/bin" ]; then
  echo "Your path is missing ~/bin, you might want to add it."
else
  echo "Your path is correctly set"
fi
38
epochwolf

Etwas wirklich einfaches und naives:

echo "$PATH"|grep -q whatever && echo "found it"

Wo auch immer das ist, wonach Sie suchen. Anstelle von && können Sie $? in eine Variable einfügen oder eine korrekte if-Anweisung verwenden.

Einschränkungen sind:

  • Das Obige wird mit den Teilstrings größerer Pfade übereinstimmen (versuchen Sie es mit "bin" und finden Sie es wahrscheinlich, obwohl "bin" nicht in Ihrem Pfad enthalten ist,/bin und/usr/bin sind.)
  • Das oben genannte erweitert Verknüpfungen nicht automatisch wie ~

Oder mit einem Perl-One-Liner:

Perl -e 'exit(!(grep(m{^/usr/bin$},split(":", $ENV{PATH}))) > 0)' && echo "found it"

Das hat immer noch die Einschränkung, dass es keine Shell-Erweiterungen ausführt, aber es scheitert nicht, wenn eine Teilzeichenfolge übereinstimmt. (Das obige stimmt mit "/usr/bin" überein, falls das nicht klar war).

5
Adam Batkin

Die Verwendung von grep ist übertrieben und kann zu Problemen führen, wenn Sie nach etwas suchen, das RE-Metazeichen enthält. Dieses Problem lässt sich mit dem [[-Befehl von bash perfekt lösen:

if [[ ":$PATH:" == *":$HOME/bin:"* ]]; then
  echo "Your path is correctly set"
else
  echo "Your path is missing ~/bin, you might want to add it."
fi

Beachten Sie, dass das Hinzufügen von Doppelpunkten vor der Erweiterung von $ PATH und dem Pfad, nach dem gesucht werden soll, das Problem der Übereinstimmung der Teilzeichenfolge löst. Wenn Sie den Pfad doppelt zitieren, werden Probleme mit Metazeichen vermieden.

116
Gordon Davisson

So geht es ohne grep:

if [[ $PATH == ?(*:)$HOME/bin?(:*) ]]

Der Schlüssel hier ist, die Doppelpunkte und Platzhalterzeichen mithilfe des Konstrukts ?() optional zu machen. Es sollte kein Problem mit Metazeichen in diesem Formular geben, aber wenn Sie Anführungszeichen hinzufügen möchten, gehen sie hier hin:

if [[ "$PATH" == ?(*:)"$HOME/bin"?(:*) ]]

Dies ist eine andere Möglichkeit, dies mit dem Übereinstimmungsoperator (=~) zu tun, sodass die Syntax eher der von grep entspricht:

if [[ "$PATH" =~ (^|:)"${HOME}/bin"(:|$) ]]
10

Es ist absolut nicht notwendig, externe Dienstprogramme wie grep zu verwenden. Hier ist, was ich verwendet habe, was auch auf ältere Versionen der Bourne Shell portierbar sein sollte.

case :$PATH: # notice colons around the value
  in *:$HOME/bin:*) ;; # do nothing, it's there
     *) echo "$HOME/bin not in $PATH" >&2;;
esac
3
tripleee

Ich habe die folgende Shell-Funktion geschrieben, um zu berichten, ob ein Verzeichnis im aktuellen PATHaufgeführt ist. Diese Funktion ist POSIX-kompatibel und kann in kompatiblen Shells wie Dash und Bash ausgeführt werden (ohne sich auf Bash-spezifische Funktionen zu verlassen).

Es enthält Funktionen zum Konvertieren eines relativen Pfads in einen absoluten Pfad. Dazu werden die Dienstprogramme readlinkoder realpathverwendet. Diese Tools werden jedoch nicht benötigt, wenn das angegebene Verzeichnis .. oder andere Links nicht als Komponenten seines Pfads enthält. Ansonsten benötigt die Funktion keine Programme außerhalb der Shell.

# Check that the specified directory exists – and is in the PATH.
is_dir_in_path()
{
  if  [ -z "${1:-}" ]; then
    printf "The path to a directory must be provided as an argument.\n" >&2
    return 1
  fi

  # Check that the specified path is a directory that exists.
  if ! [ -d "$1" ]; then
    printf "Error: ‘%s’ is not a directory.\n" "$1" >&2
    return 1
  fi

  # Use absolute path for the directory if a relative path was specified.
  if command -v readlink >/dev/null ; then
    dir="$(readlink -f "$1")"
  Elif command -v realpath >/dev/null ; then
    dir="$(realpath "$1")"
  else
    case "$1" in
      /*)
        # The path of the provided directory is already absolute.
        dir="$1"
      ;;
      *)
        # Prepend the path of the current directory.
        dir="$PWD/$1"
      ;;
    esac
    printf "Warning: neither ‘readlink’ nor ‘realpath’ are available.\n"
    printf "Ensure that the specified directory does not contain ‘..’ in its path.\n"
  fi

  # Check that dir is in the user’s PATH.
  case ":$PATH:" in
    *:"$dir":*)
      printf "‘%s’ is in the PATH.\n" "$dir"
      return 0
      ;;
    *)
      printf "‘%s’ is not in the PATH.\n" "$dir"
      return 1
      ;;
  esac
}

Der Teil, der :$PATH: verwendet, stellt sicher, dass das Muster auch übereinstimmt, wenn der gewünschte Pfad der erste oder letzte Eintrag in PATHist. Dieser clevere Trick basiert auf dieser Antwort von Glenn Jackman auf Unix & Linux .

1

$PATH ist eine Liste von Strings, die durch : getrennt sind und eine Liste von Verzeichnissen beschreiben. Ein Verzeichnis ist eine Liste von Zeichenfolgen, die durch / getrennt sind. Zwei verschiedene Zeichenfolgen können auf dasselbe Verzeichnis verweisen (wie $HOME und ~ oder /usr/local/bin und /usr/local/bin/). Also müssen wir die Regeln für das, was wir vergleichen wollen, festlegen. Ich schlage vor, die gesamten Zeichenfolgen und nicht physische Verzeichnisse zu vergleichen/zu prüfen, aber doppelte und nachgestellte / zu entfernen.

Entfernen Sie zuerst das doppelte und nachfolgende / von $PATH:

 echo $ PATH | tr -s/| sed 's/\ /: /:/g; s /:/\ n/g' 

Angenommen, $d enthält das Verzeichnis, das Sie überprüfen möchten. Dann den vorherigen Befehl weiterleiten, um $d in $PATH zu überprüfen.

 echo $ PATH | tr -s/| sed 's/\ /: /:/g; s /:/\ n/g' | grep -q "^ $ d $" || echo "fehlt $ d" 
0
jcr38

Dies ist eine Brute-Force-Methode, sie funktioniert jedoch in allen Fällen, außer wenn ein Pfadeintrag einen Doppelpunkt enthält. Es werden keine anderen Programme als die Shell verwendet.

previous_IFS=$IFS
dir_in_path='no'
export IFS=":"
for p in $PATH
do
  [ "$p" = "/path/to/check" ] && dir_in_path='yes'
done

[ "$dir_in_path" = "no" ] && export PATH="$PATH:/path/to/check"
export IFS=$previous_IFS
0
bmacnaughton