Як перевірити, чи існує програма в $ PATH?


19

Я намагаюся написати всі мої shсценарії startup / env для роботи з якомога більше DRY і стільки ж: "працює над кожним * nix, до якого я його клоную". Це означає переконатися, що якщо я спробую запустити код, якого немає, код вийде вишукано. З цією метою мені потрібно мати можливість перевірити, чи існують програми. Я знаю, як перевірити, чи існує файл, але я не впевнений, як перевірити, чи можна виконати програму в межах шляху. Я вважаю за краще використовувати $ PATH, оскільки деякі з них потребують роботи над аркою, ubuntu та centos. Деякі можуть бути встановлені в моєму homedir, в системах, де я не маю root, інші можуть бути не встановлені, а інші ще мої установки в системні шляхи.


2
Ця відповідь ТА є такою, яку я зробив у закладках для таких питань.
jw013

Відповіді:


19

Використовуйте type commandname. Це повертає істину, якщо що- commandnameнебудь виконується: псевдонім, функція, вбудована чи зовнішня команда (шукано в $PATH). Крім того, використовуйте, command commandnameщо повертає true, якщо commandnameце вбудована чи зовнішня команда (шукана в $PATH).

exists () {
  type "$1" >/dev/null 2>/dev/null
}

Є кілька варіантів sh (безумовно, до POSIX; я знаю /bin/shпід OSF1 ≤3.x та деякі версії оболонки Almquist, знайдені в ранніх версіях NetBSD та декількох дистрибутивах Linux 20 століття), де typeзавжди повертається 0 чи ні існують. Я не думаю, що жодна система поставляється з цим тисячоліттям. Якщо ви коли-небудь стикаєтеся з ними, ось функція, яку ви можете використовувати для пошуку $PATHвручну:

exists () { (
    IFS=:
    for d in $PATH; do
      if test -x "$d/$1"; then return 0; fi
    done
    return 1
) }

Ця функція, як правило, корисна, якщо ви хочете виключити вбудовані та функції та шукати ім'я в $PATH. Більшість оболонок мають вбудований для цього, command -vхоча це відносно недавнє доповнення до POSIX (все ще необов’язкове для POSIX: 2004). Це в основному зручна для програміста версія type: вона друкує повний шлях для виконуваного файлу $PATH, оголене ім’я вбудованого або функції та визначення псевдоніму для псевдоніма.

exists_in_path () {
  case $(command -v -- "$1") in
    /*) return 0;;
    alias\ *) return 1;; # alias
    *) return 1;; # built-in or function
  esac
}

Ksh, bash і zsh також повинні type -pшукати лише виконувані файли в $PATH. Зауважте, що в bash, статус повернення type -p fooдорівнює 0, якщо fooце вбудована функція; якщо ви хочете протестувати виконуваний файл у $PATH, вам потрібно перевірити, чи вихід не порожній. type -pвідсутня в POSIX; наприклад, попіл Debian (який знаходиться /bin/shна Ubuntu) не має його.


@gilles, це (чи щось подібне) if [ type keychain ]; thenне буде працювати? Я отримую помилку. /home/xenoterracide/.zshrc:84: parse error: condition expected: typeЯ припускаю, що я можу записати, що функція існує ... Я просто подумала, що це може бути простішим у певному сенсі ...
xenoterracide

@xenoterracide: відкиньте дужки!
Жил "ТАК - перестань бути злим"

Я думаю, що ти шукаєш " if type $APP >/dev/null 2>/dev/null; then ...Ти не хочеш" [].
Стівен Д

4
Ба, я знав, що повинен був освіжитися. Знову побили Жиля!
Стівен Д

type -pякщо ви спеціально шукаєте команду в $PATH(не псевдоніми або функції або вбудовані).
ефеміент

1

Якщо ви шукаєте лише зовнішні програми, ви також можете скористатися якими. Не знаю, наскільки це портативний.


3
Теоретично він менш портативний, ніж typeабо command; whichНаприклад, немає в POSIX. На практиці whichвін існує майже скрізь, але в деяких місцях (де він реалізований як csh-скрипт) він використовує інший шлях (завдяки a .cshrc), який перемагає мету.
Жил "ТАК - перестань бути злим"
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.