Подтвердить что ты не робот

Обнаруживать, имеет ли пользовательский путь определенный каталог

С /bin/bash, как бы определить, есть ли у пользователя определенный каталог в переменной $PATH?

Например

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
4b9b3361

Ответ 1

Что-то действительно простое и наивное:

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

Где то, что вы ищете. Вместо && вы можете поместить $? в переменную или использовать правильный оператор if.

Ограничения включают:

  • Вышеуказанное будет соответствовать подстрокам больших путей (попробуйте сопоставить "bin" и, вероятно, найдет его, несмотря на то, что "bin" не находится на вашем пути, /bin и/usr/bin)
  • Вышеуказанное не будет автоматически расширять ярлыки, например ~

Или используя однострочный perl:

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

У этого все еще есть ограничение на то, что он не будет выполнять каких-либо расширений оболочки, но это не сработает, если подстрока совпадает. (Вышеуказанные совпадения "/usr/bin", если это не ясно).

Ответ 2

Использование grep является излишним и может вызвать проблемы, если вы ищете что-либо, что включает метасимволы RE. Эта проблема может быть решена с помощью команды bash builtin [[:

if [[ ":$PATH:" == *":$HOME/bin:"* ]]; then
...

Обратите внимание, что добавление двоеточий перед расширением $PATH и пути для поиска разрешает проблему соответствия подстроки; двойное цитирование пути позволяет избежать проблем с метасимволами.

Ответ 3

Вот как это сделать без grep:

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

Ключ здесь состоит в том, чтобы сделать colons и wildcards необязательными, используя конструкцию ?(). Там не должно быть никаких проблем с метасимволами в этой форме, но если вы хотите включить кавычки, это куда они идут:

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

Это другой способ сделать это с помощью оператора соответствия (=~), поэтому синтаксис больше похож на grep 's:

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

Ответ 4

$PATH - список строк, разделенных символом :, которые описывают список каталогов. Каталог представляет собой список строк, разделенных символом /. Две разные строки могут указывать на один и тот же каталог (например, $HOME и ~, или /usr/local/bin и /usr/local/bin/). Поэтому мы должны исправить правила того, что мы хотим сравнить/проверить. Я предлагаю сравнивать/проверять целые строки, а не физические каталоги, но удалять дубликаты и завершать /.

Сначала удалите дубликат и конец / из $PATH:

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

Теперь предположим, что $d содержит каталог, который вы хотите проверить. Затем подключите предыдущую команду, чтобы проверить $d на $PATH.

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

Ответ 5

Я написал следующую функцию оболочки, чтобы сообщить, указан ли каталог в текущем PATH. Эта функция совместима с POSIX и будет работать в совместимых оболочках, таких как Dash и Bash (не полагаясь на Bash -специфические функции).

Он включает в себя функции для преобразования относительного пути к абсолютному пути. Для этого используются служебные программы readlink или realpath, но эти инструменты не нужны, если в поставляемом каталоге нет .. или других ссылок в качестве компонентов его пути. Помимо этого, функция не требует каких-либо программ, внешних по отношению к оболочке.

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

Часть с использованием :$PATH: гарантирует, что шаблон также будет соответствовать, если желаемый путь является первой или последней записью в PATH. Этот умный трюк основан на этом ответе Гленна Джекмана на Unix и Linux.