Как проверить, существует ли программа из скрипта Bash?

1661

Как я могу проверить, существует ли программа, которая будет либо возвращать ошибку и выйти, либо продолжить с помощью script?

Кажется, что это должно быть легко, но это меня колотило.

Теги:

35 ответов

2601
Лучший ответ

Ответ

Совместимость с POSIX:

command -v <the_command>

Для bash определенных сред:

hash <the_command> # For regular commands. Or...
type <the_command> # To check built-ins and keywords

Описание

Избегайте which. Мало того, что это внешний процесс, который вы запускаете для выполнения очень мало (это означает, что встроенные функции, такие как hash, type или command, намного дешевле), вы также можете полагаться на встроенные функции, чтобы фактически делать то, что вы хотите, в то время как эффекты внешних команд могут легко варьироваться от системы к системе.

Зачем заботиться?

  • У многих операционных систем есть which, что даже не устанавливает статус выхода, что означает, что if which foo там даже не работает и будет всегда что foo существует, даже если это не так (обратите внимание, что некоторые оболочки POSIX, похоже, тоже делают это для hash).
  • Многие операционные системы делают which обычным и злым, как изменение вывода или даже подключение к диспетчеру пакетов.

Итак, не используйте which. Вместо этого используйте один из них:

$ command -v foo >/dev/null 2>&1 || { echo >&2 "I require foo but it not installed.  Aborting."; exit 1; }
$ type foo >/dev/null 2>&1 || { echo >&2 "I require foo but it not installed.  Aborting."; exit 1; }
$ hash foo 2>/dev/null || { echo >&2 "I require foo but it not installed.  Aborting."; exit 1; }

(Незначительная сторона примечания: некоторые предполагают, что 2>&- является тем же самым 2>/dev/null, но короче - это неверно. 2>&- закрывает FD 2, который вызывает ошибку в программе, когда он пытается писать в stderr, что сильно отличается от успешной записи на него и отбрасывания вывода (и опасного!))

Если ваш хеш-трек /bin/sh, тогда вам следует заботиться о том, что говорит POSIX. type и hash коды выхода не очень хорошо определены POSIX, и hash, как видно, успешно завершает работу, когда команда не существует (еще не видели этого с type). command статус выхода хорошо определен POSIX, так что, вероятно, самый безопасный для использования.

Если ваш script использует bash, хотя правила POSIX больше не имеют значения, и оба type и hash становятся совершенно безопасными в использовании. type теперь имеет -P для поиска только PATH, а hash имеет побочный эффект, что местоположение команды будет хэшировано (для более быстрого поиска в следующий раз, когда вы его используете), что обычно хорошо, поскольку вы, вероятно, проверяете его существование, чтобы фактически использовать его.

Как простой пример, здесь функция, которая запускает gdate, если она существует, в противном случае date:

gnudate() {
    if hash gdate 2>/dev/null; then
        gdate "$@"
    else
        date "$@"
    fi
}
  • 0
    Не могли бы вы объяснить, для чего нужны части &>/dev/null и >&2 ? Линия, кажется, работает без них тоже. Благодарю.
  • 29
    @Geert: часть &> / dev / null скрывает сообщение type, которое выдается, когда foo не существует. > & 2 на эхо-сигнале обеспечивает отправку сообщения об ошибке в стандартную ошибку вместо стандартного вывода; потому что это соглашение. Они оба появляются на вашем терминале, но стандартная ошибка определенно является предпочтительным выходом для сообщений об ошибках и неожиданных предупреждений.
Показать ещё 42 комментария
340

Ниже приведен переносимый способ проверить, существует ли команда в $PATH и является исполняемым:

[ -x "$(command -v foo)" ]

Пример:

if ! [ -x "$(command -v git)" ]; then
  echo 'Error: git is not installed.' >&2
  exit 1
fi

Требуется выполнить проверку, потому что bash возвращает неисполняемый файл, если в $PATH нет исполняемого файла с этим именем.

Также обратите внимание, что если неиспользуемый файл с тем же именем, что и исполняемый файл, существует ранее в $PATH, черточка возвращает первый, хотя последний будет выполнен. Это ошибка и является нарушением стандарта POSIX. [Отчет об ошибках] [Стандарт]

Кроме того, это не удастся, если команда, которую вы ищете, была определена как псевдоним.

  • 0
    к сожалению, это не сработает на старых Bash 3.2
  • 3
    Будет ли command -v создавать путь даже для неисполняемого файла? То есть -x действительно нужен?
Показать ещё 7 комментариев
203

Я согласен с lhunath, чтобы препятствовать использованию which, и его решение отлично подходит для пользователей BASH. Однако, чтобы быть более портативным, вместо этого следует использовать command -v:

$ command -v foo >/dev/null 2>&1 || { echo "I require foo but it not installed.  Aborting." >&2; exit 1; }

Команда command совместима с POSIX, см. здесь для ее спецификации: http://pubs.opengroup.org/onlinepubs/9699919799/utilities/command.html

Примечание: type совместим с POSIX, но type -P нет.

  • 3
    То же, что и выше - exit 1; убивает xterm, если вызван оттуда.
  • 1
    Это не будет работать со стандартным sh: вы &> не действительны инструкции по перенаправлению.
Показать ещё 4 комментария
87

У меня есть функция, определенная в моем .bashrc, что делает это проще.

command_exists () {
    type "$1" &> /dev/null ;
}

Вот пример того, как он использовался (из моего .bash_profile.)

if command_exists mvim ; then
    export VISUAL="mvim --nofork"
fi
  • 0
    Что делает &> ?
  • 3
    &> Перенаправляет как stdout, так и stderr вместе.
Показать ещё 3 комментария
65

Это зависит от того, хотите ли вы знать, существует ли она в одном из каталогов в переменной $PATH или знаете ли вы ее абсолютное местоположение. Если вы хотите узнать, находится ли она в переменной $PATH, используйте

if which programname >/dev/null; then
    echo exists
else
    echo does not exist
fi

в противном случае используйте

if [ -x /path/to/programname ]; then
    echo exists
else
    echo does not exist
fi

Перенаправление в /dev/null/ в первом примере подавляет вывод программы which.

  • 21
    Вы действительно не должны использовать «который» по причинам, изложенным в моем комментарии.
30

Развернувшись на ответах @lhunath и @GregV, здесь приведен код для людей, которые хотят легко выполнить эту проверку внутри инструкции if:

exists()
{
  command -v "$1" >/dev/null 2>&1
}

Здесь, как его использовать:

if exists bash; then
  echo 'Bash exists!'
else
  echo 'Your system does not have Bash'
fi
  • 2
    Почти как неуклюжий, как это может быть. Читайте о статусе выхода в man bash и узнайте, как его использовать. Это сделает ваш код намного проще и элегантнее. Квадратные скобки не являются частью синтаксиса if , это всего лишь сокращение для командного test . if проверяет, была ли команда выполнена успешно (имеет статус выхода 0).
  • 5
    @Palec: Ты прав, это было довольно неуклюже. Я немного прибрался, и надеюсь, теперь это выглядит более подходящим.
Показать ещё 2 комментария
20

Попробуйте использовать:

test -x filename

или

[ -x filename ]

На странице bash man Условные выражения:

 -x file
          True if file exists and is executable.
  • 20
    Это означает, что вам уже нужно знать полный путь к приложению.
  • 8
    ОП не указал, хочет ли он проверить конкретный экземпляр или какой-либо исполняемый экземпляр ... Я ответил так, как прочитал.
15

Чтобы использовать hash, как @lhunath предлагает, в bash script:

hash foo &> /dev/null
if [ $? -eq 1 ]; then
    echo >&2 "foo not found."
fi

Этот script запускает hash, а затем проверяет, является ли код выхода самой последней команды, значение, хранящееся в $?, равно 1. Если hash не находит foo, код выхода будет 1. Если присутствует foo, код выхода будет 0.

&> /dev/null перенаправляет стандартную ошибку и стандартный вывод из hash, чтобы он не отображался на экране, а echo >&2 записывал сообщение в стандартную ошибку.

  • 7
    Почему бы просто, if hash foo &> /dev/null; then ... ?
8

Я никогда не получал вышеуказанные решения для работы с коробкой, к которой у меня есть доступ. Например, тип был установлен (что делает больше). Поэтому необходима встроенная директива. Эта команда работает для меня:

if [ `builtin type -p vim` ]; then echo "TRUE"; else echo "FALSE"; fi
  • 2
    Скобки не являются частью синтаксиса if , просто используйте if builtin type -p vim; then ... И обратная связь - это действительно древний и устаревший синтаксис, $() поддерживается даже sh во всех современных системах.
7

Проверьте наличие нескольких зависимостей и сообщите статус конечным пользователям.

for cmd in latex pandoc; do
  printf '%-10s' "$cmd"
  if hash "$cmd" 2>/dev/null; then
    echo OK
  else
    echo missing
  fi
done

Образец вывода:

latex     OK
pandoc    missing

Отрегулируйте 10 до максимальной длины команды. Не автоматический, потому что я не вижу не многословного способа POSIX сделать это: Как выровнять столбцы разделенной пробелами таблицы в Bash?

  • 1
    Недословный способ сделать это: 1) избавиться от спецификатора ширины; 2) добавить пробел после имени вашей команды printf; 3) направьте ваш цикл for в column -t (часть util-linux).
7

Если вы проверяете существование программы, вы, вероятно, собираетесь запустить ее позже. Почему бы не попробовать запустить его в первую очередь?

if foo --version >/dev/null 2>&1; then
    echo Found
else
    echo Not found
fi

Это более надежная проверка, что программа работает, а не просто просмотр каталогов PATH и разрешений файлов.

Кроме того, вы можете получить полезный результат из своей программы, например, ее версию.

Конечно, недостатки в том, что некоторые программы могут быть тяжелыми для запуска, а некоторые не имеют опции --version для немедленного (и успешного) выхода.

  • 0
    Этот подход я использую, чтобы проверить, установлен ли git . Это очень быстро Правда, не все команды делают это быстро и не все имеют этот флаг; хорошо упомянуть это.
6

hash foo 2>/dev/null: работает с zsh, bash, тире и золе.

type -p foo: он работает с zsh, bash и ash (busybox), но не тире (он интерпретирует -p как аргумент).

command -v foo: работает с zsh, bash, тире, но не золой (busybox) (-ash: command: not found).

Также обратите внимание, что builtin недоступно с ash и dash.

  • 0
    "Он хороший человек и тщательный"
6

Почему бы не использовать встроенные функции Bash, если вы можете?

which programname

...

type -P programname
  • 10
    А? which не является встроенным в Bash.
  • 0
    Тип -P имя программы должно быть предпочтительным, см. принятый ответ
Показать ещё 2 комментария
4

Для тех, кто заинтересован, ни одна из вышеперечисленных методологий не работает, если вы хотите обнаружить установленную библиотеку. Я полагаю, что вам остается либо физически проверять путь (возможно, для файлов заголовков и т.д.), Либо что-то вроде этого (если вы используете дистрибутив на основе Debian):

dpkg --status libdb-dev | grep -q not-installed

if [ $? -eq 0 ]; then
    apt-get install libdb-dev
fi

Как видно из вышесказанного, ответ "0" из запроса означает, что пакет не установлен. Это функция "grep" - "0" означает совпадение, "1" означает, что совпадение не найдено.

  • 0
    Согласовано. Это лучшее решение здесь, так как оно работает как для библиотек, так и для программ.
  • 10
    Тем не менее, анти-шаблон cmd; if [ $? -eq 0 ]; then следует изменить рефакторинг на if cmd; then
Показать ещё 1 комментарий
3

Я бы сказал, что нет портативного и 100% надежного способа из-за зависания alias es. Например:

alias john='ls --color'
alias paul='george -F'
alias george='ls -h'
alias ringo=/

Конечно, только последний является проблематичным (без обид на Ringo!) Но все они действительны alias es с точки зрения command -v.

Чтобы отклонить оборванные, такие как ringo, мы должны проанализировать вывод встроенной команды alias и recurse в оболочку оболочки (command -v здесь не превосходит alias). Там нет портативное решение для него, и даже Bash -специфическое решение довольно утомительно.

Обратите внимание, что такое решение безоговорочно отвергает alias ls='ls -F'

test() { command -v $1 | grep -qv alias }
  • 0
    Хорошая точка зрения. Однако при запуске из скрипта bash псевдонимы не видны.
  • 1
    Также есть проблема, она вернет false, когда команда 'alias' проверена. Когда он должен вернуть истину. Пример: тест "псевдоним"
Показать ещё 1 комментарий
3

Команда which может быть полезна. человек, который

Он возвращает 0, если исполняемый файл найден, 1, если он не найден или не выполним:

NAME

       which - locate a command

SYNOPSIS

       which [-a] filename ...

DESCRIPTION

       which returns the pathnames of the files which would be executed in the
       current environment, had its arguments been  given  as  commands  in  a
       strictly  POSIX-conformant  shell.   It does this by searching the PATH
       for executable files matching the names of the arguments.

OPTIONS

       -a     print all matching pathnames of each argument

EXIT STATUS

       0      if all specified commands are found and executable

       1      if one or more specified commands is  nonexistent  or  not  exe-
          cutable

       2      if an invalid option is specified

Хорошая вещь в том, что она выясняет, доступен ли исполняемый файл в среде, в которой выполняется, - сохраняет несколько проблем...

-Adam

  • 0
    Используйте который, если вы ищете какой-либо исполняемый файл с именем foo, но посмотрите мой ответ, если вы хотите проверить определенный файл / путь / к / a / named / foo. Также обратите внимание на то, что может быть недоступно на некоторых минимальных системах, хотя должно присутствовать на любой полноценной установке ...
  • 8
    Не полагайтесь на статус выхода которого. Многие операционные системы имеют даже тот, который не устанавливает состояние выхода, кроме 0.
2

Если внешняя команда type недоступна (как принято в виде здесь), мы можем использовать POSIX-совместимый env -i sh -c 'type cmd 1>/dev/null 2>&1':

# portable version of Bash type -P cmd (without output on stdout)
typep() {
   command -p env -i PATH="$PATH" sh -c '
      export LC_ALL=C LANG=C
      cmd="$1" 
      cmd="`type "$cmd" 2>/dev/null || { echo "error: command $cmd not found; exiting ..." 1>&2; exit 1; }`"
      [ $? != 0 ] && exit 1
      case "$cmd" in
        *\ /*) exit 0;;
            *) printf "%s\n" "error: $cmd" 1>&2; exit 1;;
      esac
   ' _ "$1" || exit 1
}

# get your standard $PATH value
#PATH="$(command -p getconf PATH)"
typep ls
typep builtin
typep ls-temp

По крайней мере, в Mac OS X 10.6.8 с использованием Bash 4.2.24 (2) command -v ls не соответствует перемещенному /bin/ls-temp.

1

Он сообщит в зависимости от местоположения, если программа существует или нет

if [ -x /usr/bin/yum ]; then
    echo This is Centos
fi
  • 0
    ням также существует в fedora ...
  • 0
    Да, я добавил эту команду, если вам нужно установить пакет в sevrer, Open suse, centos, Debian
1

Команда -v работает нормально, если для параметра <command> задана опция POSIX_BUILTINS, но может произойти сбой, если нет. (он работал у меня годами, но недавно столкнулся с тем, где он не работал).

Я считаю следующее более надежным:

test -x $(which <command>)

Так как он проверяет 3 вещи: путь, существование и разрешение на выполнение.

  • 0
    Не работает test -x $(which ls) возвращает 0, как и test -x $(which sudo) , даже если ls установлен и работает, а sudo даже не установлен в контейнере докера, в котором я работаю.
1

Здесь куча вариантов, но я не удивился, когда не было быстрых однострочных символов, это то, что я использовал в начале своих сценариев: [[ "$(command -v mvn)" ]] || { echo "mvn is not installed" 1>&2; exit 1; } [[ "$(command -v java)" ]] || { echo "java is not installed" 1>&2; exit 1; } [[ "$(command -v mvn)" ]] || { echo "mvn is not installed" 1>&2; exit 1; } [[ "$(command -v java)" ]] || { echo "java is not installed" 1>&2; exit 1; }

это основано на выбранном здесь ответе и другом источнике (и я немного поигрался).

надеюсь, что это будет полезно для других.

1

Если вы хотите проверить, существует ли программа и действительно программа, а не встроенная команда bash, то command, type и hash не являются подходящие для тестирования, поскольку все они возвращают 0 статус выхода для встроенных команд.

Например, существует программа time, которая предлагает больше возможностей, чем встроенная команда time. Чтобы проверить, существует ли программа, я бы предложил использовать which, как в следующем примере:

# first check if the time program exists
timeProg=`which time`
if [ "$timeProg" = "" ]
then
  echo "The time program does not exist on this system."
  exit 1
fi

# invoke the time program
$timeProg --quiet -o result.txt -f "%S %U + p" du -sk ~
echo "Total CPU time: `dc -f result.txt` seconds"
rm result.txt
1

Если вы не можете заставить вещи выше/ниже работать и вытаскивать волосы из своей спины, попробуйте выполнить ту же команду, используя bash -c. Просто посмотрите на этот сомнительный бред, это то, что действительно происходит при запуске $(sub-command):

Во-первых. Это может дать вам совершенно другой выход.

$ command -v ls
alias ls='ls --color=auto'
$ bash -c "command -v ls"
/bin/ls

Во-вторых. Он не может дать вам никакого вывода.

$ command -v nvm
nvm
$ bash -c "command -v nvm"
$ bash -c "nvm --help"
bash: nvm: command not found
  • 0
    Различия вызваны различием между интерактивным и неинтерактивным режимами оболочки. Ваш ~ / .bashrc доступен только для чтения, когда оболочка не авторизована и интерактивна. Второй выглядит странно, потому что это должно быть вызвано разницей в переменной окружения PATH, но подоболочки наследуют среду.
  • 0
    В моем случае .bashrc имеет [ -z "$PS1" ] && return добавлением # If not running interactively, don't do anything поэтому я полагаю, что это причина того, что даже явное получение bashrc в неинтерактивном режиме не ' Т помочь. Проблема может быть решена путем вызова скрипта с помощью точечного оператора ss64.com/bash/source.html . ./script.sh но это не то, о чем каждый хотел бы помнить, чтобы печатать каждый раз.
Показать ещё 3 комментария
1

моя настройка для сервера debian. У меня возникла проблема, когда несколько пакетов содержат одно и то же имя. например apache2. так это было моим решением.

function _apt_install() {
    apt-get install -y $1 > /dev/null
}

function _apt_install_norecommends() {
    apt-get install -y --no-install-recommends $1 > /dev/null
}
function _apt_available() {
    if [ `apt-cache search $1 | grep -o "$1" | uniq | wc -l` = "1" ]; then
        echo "Package is available : $1"
        PACKAGE_INSTALL="1"
    else
        echo "Package $1 is NOT available for install"
        echo  "We can not continue without this package..."
        echo  "Exitting now.."
        exit 0
    fi
}
function _package_install {
    _apt_available $1
    if [ "${PACKAGE_INSTALL}" = "1" ]; then
        if [ "$(dpkg-query -l $1 | tail -n1 | cut -c1-2)" = "ii" ]; then
             echo  "package is already_installed: $1"
        else
            echo  "installing package : $1, please wait.."
            _apt_install $1
            sleep 0.5
        fi
    fi
}

function _package_install_no_recommends {
    _apt_available $1
    if [ "${PACKAGE_INSTALL}" = "1" ]; then
        if [ "$(dpkg-query -l $1 | tail -n1 | cut -c1-2)" = "ii" ]; then
             echo  "package is already_installed: $1"
        else
            echo  "installing package : $1, please wait.."
            _apt_install_norecommends $1
            sleep 0.5
        fi
    fi
}
1

Во-вторых, использование команды -v. Например. например:

md=$(command -v mkdirhier) ; alias md=${md:=mkdir}  # bash

emacs="$(command -v emacs) -nw" || emacs=nano
alias e=$emacs
[[ -z $(command -v jed) ]] && alias jed=$emacs
1

В хэш-варианте есть одна ошибка: в командной строке вы можете, например, ввести

one_folder/process

чтобы выполнить процесс. Для этого родительская папка one_folder должна находиться в $PATH. Но когда вы пытаетесь хешировать эту команду, она всегда будет успешной:

hash one_folder/process; echo $? # will always output '0'
  • 3
    «Для этого родительская папка one_folder должна быть в $PATH » - это совершенно неточно. Попытайся. Чтобы это работало, one_folder должен быть в текущем каталоге .
1

Чтобы подражать Bash type -P cmd, мы можем использовать POSIX-совместимый env -i type cmd 1>/dev/null 2>&1.

man env
# "The option '-i' causes env to completely ignore the environment it inherits."
# In other words, there are no aliases or functions to be looked up by the type command.

ls() { echo 'Hello, world!'; }

ls
type ls
env -i type ls

cmd=ls
cmd=lsx
env -i type $cmd 1>/dev/null 2>&1 || { echo "$cmd not found"; exit 1; }
  • 7
    Почему за это проголосовали? В каких системах это действительно работает для вас? type кажется builtin в большинстве оболочек, поэтому это не может работать, потому что env использует execvp для запуска command поэтому command не может быть builtinbuiltin всегда будет выполняться в одной и той же среде). Это не работает для меня в bash , ksh93 , zsh , busybox [a]sh и dash которые предоставляют type как встроенную оболочку.
0

Script

#!/bin/bash

# Commands found in the hash table are checked for existence before being
# executed and non-existence forces a normal PATH search.
shopt -s checkhash

function exists() {
 local mycomm=$1; shift || return 1

 hash $mycomm 2>/dev/null || \
 printf "\xe2\x9c\x98 [ABRT]: $mycomm: command does not exist\n"; return 1;
}
readonly -f exists

exists notacmd
exists bash
hash
bash -c 'printf "Fin.\n"'

Результат

✘ [ABRT]: notacmd: command does not exist
hits    command
   0    /usr/bin/bash
Fin.
0

Я использую это, потому что это очень просто:

if [ `LANG=C type example 2>/dev/null|wc -l` = 1 ];then echo exists;else echo "not exists";fi

или

if [ `LANG=C type example 2>/dev/null|wc -l` = 1 ];then
echo exists
else echo "not exists"
fi

Он использует shell builtin и статус программного эха для stdout и ничего для stderr с другой стороны, если команда не найдена, она имеет статус echos только для stderr.

0
checkexists() {
    while [ -n "$1" ]; do
        [ -n "$(which "$1")" ] || echo "$1": command not found
        shift
    done
}
  • 2
    Код полезен, но слова действительно добиваются многого при публикации после многих других ответов, попробуйте когда-нибудь :)
0

Мне пришлось проверить, был ли установлен git как часть развертывания нашего CI-сервера. Мой последний bash script был следующим (сервер Ubuntu):

if ! builtin type -p git &>/dev/null; then
  sudo apt-get -y install git-core
fi

Надеюсь, что это поможет кому-то еще!

  • 3
    Условие довольно бесполезно, по модулю время запуска для запуска apt-get, так как apt-get будет удовлетворен и завершится, если git-core уже установлен.
  • 2
    Время его запуска не является ничтожным, но более важной мотивацией является sudo : без условия он всегда останавливается и запрашивает пароль (если вы недавно не сделали sudo). Кстати, может быть полезно выполнить sudo -p "Type your password to install missing git-core: " чтобы приглашение не появлялось на ровном месте.
-1

Я бы просто попытался вызвать программу, например, с --version или --help и проверить, была ли команда выполнена успешно или нет

Используемый с set -e скрипт завершит работу, если программа не найдена, и вы получите значимое сообщение об ошибке:

#!/bin/bash
set -e
git --version >> /dev/null
-1

Я использую очень удобную и короткую версию:

dpkg -s curl 2>/dev/null >/dev/null || apt-get -y install curl

Это так просто, если нужно проверить только одну программу.

-1
GIT=/usr/bin/git                     # STORE THE RELATIVE PATH
# GIT=$(which git)                   # USE THIS COMMAND TO SEARCH FOR THE RELATIVE PATH

if [[ ! -e $GIT ]]; then             # CHECK IF THE FILE EXISTS
    echo "PROGRAM DOES NOT EXIST."
    exit 1                           # EXIT THE PROGRAM IF IT DOES NOT
fi

# DO SOMETHING ...

exit 0                               # EXIT THE PROGRAM IF IT DOES
  • 1
    1) Это абсолютный путь. 2) Вы только проверяете, существует ли программа в определенном месте , а не вызывается. Вместо этого у меня может быть что-то в /usr/local/bin и ваш код завершится
-2

Потрясающий ответ и объяснение от @lhunath. Спас мой день. Я немного расширил это. Не мог контролировать себя, разделяя это - надеясь, что это может быть полезно для кого-то. Если кто-то должен проверить (массив) нескольких программ, вот быстрый фрагмент.

Что он делает? (1) Читать массив программ. (2) Показать сообщение об ошибке программы. (3) Предложить пользователю продолжить (принудительный цикл) опции y/n для проверки остальных программ.

#!/bin/bash

proginstalldir=/full/dir/path/of/installation
progsbindir=$proginstalldir/bin
echo -e "\nMy install directory - $proginstalldir"
echo -e "My binaries directory - $progsbindir"

VerifyInstall () {
clear
myprogs=( program1 program2 program3 program4 program5 programn ); 
echo -e "\nValidation of my programs started...."
for ((i=0; i<${#myprogs[@]}; i++)) ; do 
command -v $progsbindir/${myprogs[i]} >/dev/null && echo -e "Validating....\t${myprogs[i]}\tSUCCESSFUL"  || { echo -e "Validating.... \t${myprogs[i]}\tFAILED" >&2;
while true; do 
printf "%s:  "  "ERROR.... Validation FAILED for ${myprogs[i]} !!!! Continue?"; read yn; 
case $yn in [Yy] )  echo -e "Please wait..." ; break;;
[Nn]) echo -e "\n\n#################################\n##   Validation Failed .. !!   ##\n#################################\n\n" ; exit 1; break;;
*) echo -e "\nPlease answer y or n then press Enter\n"; esac; done; >&2; }; done
sleep 2
}

VerifyInstall
  • 0
    Если вы знаете абсолютный путь, вам не нужна command -v
  • 0
    Почему проголосовали? И если это из-за комментария от Чжоу, где я упомянул, что нам нужен -v, если мы знаем абсолютный путь. Я просто поделился и четко сказал, что немного расширил. Вопросительный знак.
-3

Я не мог заставить одно из решений работать, но после его редактирования я немного придумал это. Что работает для меня:

dpkg --get-selections | grep -q linux-headers-$(uname -r)

if [ $? -eq 1 ]; then
        apt-get install linux-headers-$(uname -r)
fi
  • 0
    Это работает только для систем на основе Debian, таких как Ubuntu.
  • 0
    Даже для этих систем может произойти сбой, если команда не установлена через dpkg или apt .

Ещё вопросы

Сообщество Overcoder
Наверх
Меню