Jak mogę sprawdzić, czy program istnieje ze skryptu Bash?

Jak sprawdzić, czy program istnieje, w sposób, który zwróci błąd i zakończy działanie, lub będzie kontynuował działanie skryptu?

Wydaje się, że powinno być łatwo, ale mnie to dręczy.

 2415
Author: Peter Mortensen, 2009-02-26

30 answers

Odpowiedź

Zgodny z POSIX:

command -v <the_command>

Przykładowe użycie:

if ! command -v COMMAND &> /dev/null
then
    echo "COMMAND could not be found"
    exit
fi

Dla środowisk specyficznych dla Bash:

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

Wyjaśnienie

Unikaj which. Nie tylko jest to zewnętrzny proces, który uruchamiasz, aby zrobić bardzo mało (co oznacza, że zbudowany jest jak hash, type lub command są znacznie tańsze), można również polegać na wbudowanych, aby rzeczywiście zrobić to, co chcesz, podczas gdy efekty zewnętrznych poleceń mogą się łatwo różnić w zależności od systemu.

Dlaczego troska?

  • wiele systemów operacyjnych ma which, który nawet nie ustawia statusu zakończenia , co oznacza, że if which foonawet tam nie będzie działać i zawsze zgłosi, że foo istnieje, nawet jeśli tak nie jest (zauważ, że niektóre powłoki POSIX wydają się to robić również dla hash).
  • wiele systemów operacyjnych sprawia, że which robi niestandardowe i złe rzeczy, takie jak zmiana wyjścia lub nawet hook do menedżera pakietów.

Więc nie używaj which. Zamiast tego użyj jednego z te:

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

(Minor side-notatka: niektórzy sugerują, że 2>&- jest tym samym 2>/dev/null, ale krótszym – jest to nieprawda . 2>&- zamyka FD 2, co powoduje błąd w programie, gdy próbuje zapisać na stderr, co bardzo różni się od pomyślnego zapisu do niego i odrzucenia wyjścia (i jest niebezpieczne!))

Jeśli twój hash bang to /bin/sh, powinieneś dbać o to, co mówi POSIX. Kod wyjścia type i hash nie są zbyt dobrze zdefiniowane przez POSIX, a hash jest seen zakończy się pomyślnie, gdy polecenie nie istnieje(nie widziałem tego jeszcze z type). Status wyjścia command jest dobrze zdefiniowany przez POSIX, więc jest prawdopodobnie najbezpieczniejszy w użyciu.

Jeśli twój skrypt używa bash, reguły POSIX nie mają już znaczenia i zarówno type, jak i hash stają się całkowicie bezpieczne w użyciu. type teraz ma -P do wyszukiwania tylko PATH i hash ma efekt uboczny, że lokalizacja polecenia zostanie zahaszowana( dla szybszego wyszukiwania następnym razem), co jest zazwyczaj jest to dobra rzecz, ponieważ prawdopodobnie sprawdzasz jego istnienie, aby faktycznie z niego korzystać.

Jako prosty przykład, oto funkcja, która działa gdate jeśli istnieje, w przeciwnym razie date:

gnudate() {
    if hash gdate 2>/dev/null; then
        gdate "$@"
    else
        date "$@"
    fi
}

Alternatywa z kompletnym zestawem funkcji

Możesz użyć skryptów-common , aby zaspokoić swoje potrzeby.

Aby sprawdzić, czy coś jest zainstalowane, możesz zrobić:

checkBin <the_command> || errorMessage "This tool requires <the_command>. Install it please, and then run this tool again."
 3363
Author: lhunath,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-07-01 07:05:49

Poniżej znajduje się przenośny sposób sprawdzenia, czy polecenie istnieje w $PATH i {[7] } jest wykonywalne:

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

Przykład:

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

Sprawdzenie wykonywalności jest potrzebne, ponieważ bash zwraca plik nie wykonywalny, jeśli w $PATH nie znaleziono pliku wykonywalnego o tej nazwie.

Zauważ również, że jeśli plik nie wykonywalny o tej samej nazwie co plik wykonywalny istnieje wcześniej w $PATH, dash zwraca pierwszy plik, nawet jeśli drugi zostanie wykonany. To jest błąd i jest w naruszenie standardu POSIX. [Zgłoś błąd] [Standard ]

Ponadto nie powiedzie się, jeśli szukana komenda została zdefiniowana jako alias.

 640
Author: nyuszika7h,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-10-26 14:18:46

Zgadzam się z lhunathem, aby zniechęcić do używania which, a jego rozwiązanie jest w pełni poprawne dla użytkowników Basha . Jednakże, aby być bardziej przenośnym, command -v stosuje się zamiast tego:

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

Polecenie {[3] } jest zgodne z POSIX. Zobacz jego specyfikację tutaj: command-wykonaj proste polecenie

Uwaga: type jest zgodny z POSIX, ale type -P nie jest.

 215
Author: GregV,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-01-16 03:25:42

Mam funkcję zdefiniowaną w moim .bashrc to ułatwia.

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

Oto przykład jak to jest używane (z mojego .bash_profile.)

if command_exists mvim ; then
    export VISUAL="mvim --nofork"
fi
 95
Author: Josh Strater,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-10-14 09:24:40

To zależy od tego, czy chcesz wiedzieć, czy istnieje w jednym z katalogów w zmiennej $PATH, czy też znasz jej absolutną lokalizację. Jeśli chcesz wiedzieć, czy jest w zmiennej $PATH, Użyj

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

W przeciwnym razie użyj

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

Przekierowanie do /dev/null/ w pierwszym przykładzie blokuje wyjście programu which.

 89
Author: dreamlax,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-01-16 03:17:13

Rozszerzając odpowiedzi @lhunath i @ GregV, oto kod dla osób, które chcą łatwo umieścić ten czek wewnątrzif:

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

Oto jak go używać:

if exists bash; then
  echo 'Bash exists!'
else
  echo 'Your system does not have Bash'
fi
 40
Author: Romário,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-12-11 20:42:45

Spróbuj użyć:

test -x filename

Lub

[ -x filename ]

Ze strony podręcznika Bash Pod wyrażenia warunkowe :

 -x file
          True if file exists and is executable.
 24
Author: dmckee --- ex-moderator kitten,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-01-16 03:10:14

Aby użyć hash, jak sugeruje @lhunath, w skrypcie Basha:

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

Ten skrypt uruchamia hash, a następnie sprawdza, czy kod zakończenia najnowszego polecenia, wartość zapisana w $?, jest równa 1. Jeśli hash nie znajdzie foo, kodem wyjścia będzie 1. Jeśli foo jest obecny, kod wyjścia to 0.

&> /dev/null przekierowuje standardowy błąd i standardowe wyjście z hash, aby nie pojawił się na ekranie i echo >&2 zapisuje wiadomość do standardowego błędu.

 17
Author: dcharles,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-01-16 03:30:20

Jeśli sprawdzisz istnienie programu, prawdopodobnie i tak go uruchomisz później. Dlaczego nie spróbować uruchomić go w pierwszej kolejności?

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

Jest to bardziej wiarygodne sprawdzenie, czy program działa, niż Przeglądanie katalogów ścieżek i uprawnień do plików.

Dodatkowo możesz uzyskać przydatne wyniki z twojego programu, takie jak jego wersja.

Oczywiście wadą jest to, że niektóre programy mogą być ciężkie do uruchomienia, a niektóre nie mają --version opcji natychmiastowego (i pomyślnie) wyjść.

 9
Author: 0xF,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-07-08 15:14:30

Nigdy nie dostałem poprzednich odpowiedzi do pracy nad pudełkiem, do którego mam dostęp. Po pierwsze, type został zainstalowany (robiąc co more robi). Potrzebna jest więc dyrektywa wbudowana. To polecenie działa dla mnie:

if [ `builtin type -p vim` ]; then echo "TRUE"; else echo "FALSE"; fi
 9
Author: Magnus,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-01-16 03:20:17

Sprawdź wiele zależności i poinformuj użytkowników końcowych o statusie

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

Przykładowe wyjście:

latex     OK
pandoc    missing

Dostosuj 10 do maksymalnej długości polecenia. Nie jest to automatyczne, ponieważ nie widzę na to sposobu non-verbose POSIX: Jak wyrównać kolumny oddzielonej spacjami tabeli w Bash?

Sprawdź, czy niektóre pakiety apt są zainstalowane z dpkg -s i zainstaluj je w przeciwnym razie .

Zobacz: sprawdź czy apt-get Pakiet jest zainstalowany, a następnie zainstaluj go, jeśli nie jest na Linuksie

Była wcześniej wspominana na: Jak mogę sprawdzić, czy program istnieje ze skryptu Bash?

 9
Author: Ciro Santilli TRUMP BAN IS BAD,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-01-16 03:39:18

Jest tu mnóstwo opcji, ale byłem zaskoczony, że nie ma szybkich jednolinijkowych. To jest to, czego użyłem na początku moich skryptów:

[[ "$(command -v mvn)" ]] || { echo "mvn is not installed" 1>&2 ; exit 1; }
[[ "$(command -v java)" ]] || { echo "java is not installed" 1>&2 ; exit 1; }

Jest to oparte na wybranej tutaj odpowiedzi i innym źródle.

 7
Author: keisar,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-01-16 12:45:09

Polecenie -v działa poprawnie, jeśli opcja POSIX_BUILTINS jest ustawiona dla <command> do testowania, ale może się nie udać, jeśli nie. (To działa dla mnie od lat, ale ostatnio natknąłem się na jeden, gdzie nie działa.)

Uważam, że następujące są bardziej odporne na awarie:

test -x "$(which <command>)"

Ponieważ testuje trzy rzeczy: ścieżkę, istnienie i pozwolenie na wykonanie.

 7
Author: AnthonyC,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-12-17 20:51:48

hash foo 2>/dev/null: współpracuje Z Z shell (Zsh), Bash, Dash i ash .

type -p foo: wydaje się, że działa z powłoką z, Bash i ash (BusyBox ), ale nie Dash (interpretuje -p jako argument).

command -v foo: działa Z Z shell, Bash, Dash, ale nie z ash (BusyBox) (-ash: command: not found).

Należy również pamiętać, że {[5] } nie jest dostępny z ash i Dash.

 6
Author: blueyed,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-01-16 03:44:13

Użyj Bash builtins, jeśli możesz:

which programname

...

type -P programname
 4
Author: Peter Mortensen,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-01-16 03:17:44

Dla zainteresowanych, żadna z metod w poprzednich odpowiedziach nie działa, jeśli chcesz wykryć zainstalowaną bibliotekę. Domyślam się, że możesz albo fizycznie sprawdzić ścieżkę (potencjalnie dla plików nagłówkowych itp.), Albo coś w tym stylu (jeśli jesteś na dystrybucji opartej na Debianie):

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

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

Jak widać z powyższego, odpowiedź "0" z zapytania oznacza, że pakiet nie jest zainstalowany. Jest to funkcja "grep" - a " 0 "oznacza, że znaleziono dopasowanie, a" 1 " oznacza, że nie było dopasowania znaleziono.

 4
Author: Nathan Crause,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-01-16 03:23:07

Powiedziałbym, że nie ma żadnego przenośnego i 100% niezawodnego sposobu ze względu na wiszące aliases. Na przykład:

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

Oczywiście tylko ten ostatni jest problematyczny (bez urazy dla Ringo!). Ale wszystkie z nich są ważne alias es z punktu widzenia command -v.

Aby odrzucić zwisające takie jak ringo, musimy przeanalizować wyjście wbudowanego w powłokę polecenia alias i wprowadzić do nich rekurencję (command -v nie jest tutaj nadrzędna wobec alias.) Nie ma na to żadnego przenośnego rozwiązania, a nawet Rozwiązanie specyficzne dla Bash jest dość żmudne.

Zauważ, że takie rozwiązanie bezwarunkowo odrzuci alias ls='ls -F':

test() { command -v $1 | grep -qv alias }
 2
Author: nodakai,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-01-16 12:39:43

To powie w zależności od lokalizacji, czy program istnieje, czy nie:

    if [ -x /usr/bin/yum ]; then
        echo "This is Centos"
    fi
 2
Author: Klevin Kona,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-04-07 12:55:28

Moja konfiguracja serwera Debian :

Miałem problem, gdy wiele pakietów zawierało tę samą nazwę.

Na przykład apache2. Więc to było moje rozwiązanie:

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
Author: ThCTLo,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-01-16 03:50:53

Jeśli wy / dziewczyny nie możecie dostać rzeczy w odpowiedziach tutaj do pracy i wyrywają włosy z pleców, spróbuj uruchomić tę samą komendę za pomocą bash -c. Spójrz na to somnambular delirium. Tak naprawdę dzieje się to po uruchomieniu $(sub-command):

Pierwszy. Może dać zupełnie inną wydajność.

$ command -v ls
alias ls='ls --color=auto'
$ bash -c "command -v ls"
/bin/ls
Druga. Może w ogóle nie dawać żadnych wyników.
$ command -v nvm
nvm
$ bash -c "command -v nvm"
$ bash -c "nvm --help"
bash: nvm: command not found
 1
Author: user619271,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-01-16 11:36:46

Jeśli chcesz sprawdzić, czy program istnieje i jest naprawdę programem, a nie wbudowanym poleceniem Bash , to command, type i hash nie są odpowiednie do testowania, ponieważ wszystkie zwracają 0 status zakończenia dla wbudowanych poleceń.

Na przykład istnieje program time , który oferuje więcej funkcji niż wbudowane polecenie time. Aby sprawdzić, czy program istnieje, proponuję użyć which jak w poniższym przykładzie:

# 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
Author: rpr,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-01-16 12:42:15

Chciałem odpowiedzieć na to samo pytanie, ale uruchomić w pliku Makefile.

install:
    @if [[ ! -x "$(shell command -v ghead)" ]]; then \
        echo 'ghead does not exist. Please install it.'; \
        exit -1; \
    fi
 1
Author: Richard A Quadling,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-06-04 09:15:00

To może być prostsze, po prostu:

#!/usr/bin/env bash                                                                
set -x                                                                             

# if local program 'foo' returns 1 (doesn't exist) then...                                                                               
if ! type -P foo; then                                                             
    echo 'crap, no foo'                                                            
else                                                                               
    echo 'sweet, we have foo!'                                                    
fi                                                                                 

Zmień foo na vi, aby drugi warunek wystrzelił.

 1
Author: todd_dsm,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-06-15 20:43:00

Wariant skrótu ma jedną pułapkę: w wierszu poleceń można na przykład wpisać

one_folder/process

Aby proces został wykonany. W tym celu folder nadrzędny one_folder musi znajdować się w $PATH. Ale kiedy spróbujesz zahaszować to polecenie, zawsze się powiedzie:

hash one_folder/process; echo $? # will always output '0'
 0
Author: anycast.cw,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-12-14 12:41:26

Popieram użycie "command-v". Np. tak:

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
 0
Author: user2961933,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-11-06 19:06:48

Polecenie which może być przydatne. człowiek, który

Zwraca 0, jeśli plik wykonywalny został znaleziony i zwraca 1, jeśli nie został znaleziony lub nie jest wykonywalny:

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 executable

       2      if an invalid option is specified

Fajną rzeczą w which jest to, że wykrywa, czy plik wykonywalny jest dostępny w środowisku, w którym jest uruchomiony which - oszczędza to kilka problemów...

 0
Author: Adam Davis,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-01-16 03:15:08

Musiałem sprawdzić, czy Git został zainstalowany w ramach wdrażania naszego serwera CI. Mój ostatni skrypt Bash wyglądał następująco (Ubuntu server):

if ! builtin type -p git &>/dev/null; then
  sudo apt-get -y install git-core
fi
 0
Author: Greg K,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-01-16 03:27:26

Aby naśladować Basha type -P cmd, Możemy użyć standardu 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; }
 0
Author: tim,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-01-16 03:28:20

Jeśli nie ma dostępnych zewnętrznych poleceń type (jako oczywiste tutaj), możemy użyć zgodnego z POSIX env -i sh -c 'type cmd 1>/dev/null 2>&1':

# Portable version of Bash's 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

Przynajmniej na Mac OS X v10.6.8 (Snow Leopard) używanie Bash 4.2.24 (2) command -v ls nie pasuje do przeniesionego /bin/ls-temp.

 0
Author: freno,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-01-16 03:47:03

/ Align = "left" /

Sprawdzam tylko czy Komenda którą wykonuję zwraca kod błędu. Jeśli zwróci 0 oznacza to, że program jest zainstalowany. Ponadto możesz użyć tego do sprawdzenia wyjścia skryptu. Weźmy na przykład ten skrypt.

Foo.sh

#!/bin/bash
echo "hello world"
exit 1 # throw some error code

Przykłady:

# outputs something bad... and exits
bash foo.sh $? -eq 0 || echo "something bad happened. not installed" ; exit 1

# does NOT outputs nothing nor exits because dotnet is installed on my machine
dotnet --version $? -eq 0 || echo "something bad happened. not installed" ; exit 1

W zasadzie wszystko, co robisz, to sprawdzanie kodu zakończenia uruchomienia polecenia. najbardziej akceptowana odpowiedź na to pytanie zwróci true, nawet jeśli Komenda zakończy kod nie jest 0.

 0
Author: Tono Nam,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-10-14 20:10:26