etc./StackOverFlow

Bash 스크립트에서 프로그램이 있는지 어떻게 확인할 수 있습니까?

청렴결백한 만능 재주꾼 2021. 11. 13. 00:14
반응형

질문자 :gregh


오류를 반환하고 종료하거나 스크립트를 계속하는 방식으로 프로그램이 존재하는지 확인하려면 어떻게 해야 합니까?

쉬워야 할 것 같으면서도 막막하네요.



답변

POSIX 호환:

 command -v <the_command>

사용 예:

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

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'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; }

(사소한 참고 사항: 일부는 2>&-2>/dev/null 같지만 더 짧다고 제안합니다. 이것은 사실이 아닙니다 2>&- FD 2를 닫고 stderr에 쓰려고 할 때 프로그램에 오류가 발생합니다. , 성공적으로 작성하고 출력을 버리는 것과는 매우 다릅니다(위험합니다!))

해시 뱅이 /bin/sh 이면 POSIX가 말하는 내용에 주의해야 합니다. typehash 의 종료 코드는 POSIX에 의해 아주 잘 정의되어 있지 않으며, hash 는 명령이 존재하지 않을 때 성공적으로 종료되는 것으로 보입니다( type 에서 이것을 본 적이 없습니다). command 의 종료 상태는 POSIX에 의해 잘 정의되어 있으므로 아마도 사용하기에 가장 안전할 것입니다.

스크립트가 bash 사용한다면 POSIX 규칙은 더 이상 중요하지 않으며 typehash 모두 사용하기에 완벽하게 안전해집니다. 이제 type PATH 만 검색 -P 가 있고 hash 에는 명령의 위치가 해시된다는 부작용이 있습니다(다음 번에 사용할 때 더 빠른 조회를 위해). 실제로 사용하기 위해.

gdate 를 실행하고 그렇지 않은 경우 date 를 실행하는 함수가 있습니다.

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

완전한 기능 세트가 있는 대안

필요에 따라 scripts-common 을 사용할 수 있습니다.

무언가가 설치되어 있는지 확인하려면 다음을 수행할 수 있습니다.

 checkBin <the_command> || errorMessage "This tool requires <the_command>. Install it please, and then run this tool again."

lhunath

$PATH 있고 실행 가능한지 확인하는 이식 가능한 방법입니다.

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

예시:

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

$PATH 에 해당 이름의 실행 파일이 없으면 bash가 실행 불가능한 파일을 반환하기 때문에 실행 가능한 검사가 필요합니다.

또한 실행 파일과 이름이 같은 실행 불가능한 파일이 $PATH 이전에 존재하는 경우 dash는 후자가 실행되더라도 전자를 반환합니다. 이것은 버그이며 POSIX 표준을 위반합니다. [ 버그 리포트 ] [ 표준 ]

또한 찾고 있는 명령이 별칭으로 정의된 경우 실패합니다.


nyuszika7h

나는의 사용을 억제하기 위해 lhunath에 동의 하고, 그 해결책은 배쉬 사용자를위한 완벽하게 유효합니다. which 그러나 이식성을 command -v 대신 사용해야 합니다.

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

명령 command 은 POSIX와 호환됩니다. 사양은 여기를 참조하십시오. 명령 - 간단한 명령을 실행합니다.

참고: type 은 POSIX와 호환되지만 type -P 는 호환되지 않습니다.


GregV

내 .bashrc에 정의된 함수가 있어 이를 더 쉽게 만듭니다.

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

다음은 사용 방법의 예입니다(내 .bash_profile 에서).

 if command_exists mvim ; then export VISUAL="mvim --nofork" fi

Josh Strater

$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 프로그램의 출력이 표시되지 않습니다.


dreamlax

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

Romário

다음을 사용해보십시오.

 test -x filename

또는

 [ -x filename ]

조건식 아래의 Bash 맨페이지에서 :

 -x file True if file exists and is executable.

dmckee --- ex-moderator kitten

Bash 스크립트에서 @lhunath가 제안한 것처럼 hash 를 사용하려면:

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

이 스크립트는 hash 실행한 다음 가장 최근 명령의 종료 코드가 $? 1 과 같습니다. hash foo 찾지 못하면 종료 코드는 1 입니다. foo 가 있으면 종료 코드는 0 입니다.

&> /dev/nullhash 표준 오류표준 출력 을 리디렉션하여 화면에 나타나지 않고 echo >&2 는 메시지를 표준 오류에 씁니다.


dcharles

명령 -v <command> 에 대해 POSIX_BUILTINS 옵션이 설정되어 있으면 제대로 작동하지만 그렇지 않으면 실패할 수 있습니다. (몇 년 동안 효과가 있었지만 최근에 작동하지 않는 문제에 부딪쳤습니다.)

다음이 더 안전하다고 생각합니다.

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

경로, 존재 및 실행 권한의 세 가지를 테스트하기 때문입니다.


AnthonyC

프로그램 존재 여부를 확인하면 나중에라도 실행하게 될 것입니다. 처음부터 실행해 보지 않겠습니까?

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

단순히 PATH 디렉토리와 파일 권한을 보는 것보다 프로그램이 실행되는지 확인하는 것이 더 신뢰할 수 있습니다.

또한 프로그램의 버전과 같은 유용한 결과를 얻을 수 있습니다.

물론 단점은 일부 프로그램은 시작하기에 무거울 수 있고 일부는 즉시(그리고 성공적으로) 종료 --version


0xF

여기에는 수많은 옵션이 있지만 빠른 단일 라이너가 없다는 사실에 놀랐습니다. 이것은 내 스크립트의 시작 부분에서 사용한 것입니다.

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

이것은 여기에서 선택한 답변과 다른 출처를 기반으로 합니다.


keisar

내가 액세스할 수 있는 상자에 대한 이전 답변을 얻지 못했습니다. 하나를 들어, type (일을 설치 한 more 않음). 따라서 내장 지시문이 필요합니다. 이 명령은 저에게 효과적입니다.

 if [ `builtin type -p vim` ]; then echo "TRUE"; else echo "FALSE"; fi

Magnus

여러 종속성을 확인하고 최종 사용자에게 상태를 알립니다.

 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에서 공백으로 구분된 테이블의 열을 어떻게 정렬할 수 있습니까?

apt 패키지가 dpkg -s 로 설치되었는지 확인하고 그렇지 않으면 설치하십시오 .

참조: apt-get 패키지가 설치되어 있는지 확인한 다음 Linux에 없으면 설치하십시오.

이전에 다음에서 언급했습니다. Bash 스크립트에서 프로그램이 존재하는지 어떻게 확인할 수 있습니까?


Ciro Santilli 新疆再教育营六四事件法轮功郝海东

hash foo 2>/dev/null : Z 셸(Zsh), Bash, Dashash에서 작동 합니다.

type -p foo : Z 셸, Bash 및 ash( BusyBox )에서는 작동하지만 Dash에서는 작동하지 않는 -p 를 인수로 해석함).

command -v foo : Z 셸, Bash, Dash에서는 작동하지만 ash(BusyBox)에서는 작동하지 않습니다( -ash: command: not found ).

또한 builtin 은 ash 및 Dash와 함께 사용할 수 없습니다.


blueyed

다음과 같은 경우 Bash 내장을 사용하십시오.

 which programname

...

 type -P programname

bin

관심있는 사람들을 위해 설치된 라이브러리를 감지하려는 경우 이전 답변의 방법론이 작동하지 않습니다. 물리적으로 경로(헤더 파일 등의 경우)를 확인하거나 다음과 같은 내용(데비안 기반 배포판을 사용하는 경우)이 남아 있다고 생각합니다.

 dpkg --status libdb-dev | grep -q not-installed if [ $? -eq 0 ]; then apt-get install libdb-dev fi

위에서 알 수 있듯이 쿼리의 "0" 응답은 패키지가 설치되지 않았음을 의미합니다. 이것은 "grep"의 기능입니다. "0"은 일치하는 항목이 있음을 의미하고 "1"은 일치하는 항목이 없음을 의미합니다.


Nathan Crause

프로그램이 있는지 여부를 위치에 따라 알려줍니다.

 if [ -x /usr/bin/yum ]; then echo "This is Centos" fi

Klevin Kona

alias 으로 인해 이식 가능하고 100% 신뢰할 수 있는 방법은 없다고 말하고 싶습니다. 예를 들어:

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

물론 마지막 문제만 문제가 됩니다(Ringo에게 불쾌감을 주지 않습니다!). 그러나 모두 command -v 의 관점에서 alias 입니다.

ringo 와 같은 댕글링을 거부 alias 명령의 출력을 구문 분석하고 재귀해야 합니다(여기서 command -v alias 보다 우수하지 않습니다). 이에 대한 이식 가능한 솔루션은 없습니다. , 그리고 Bash 전용 솔루션조차도 다소 지루합니다.

이와 같은 솔루션은 alias ls='ls -F' 을 무조건 거부합니다.

 test() { command -v $1 | grep -qv alias }

nodakai

나는 같은 질문에 대답하기를 원했지만 Makefile 내에서 실행하기를 원했습니다.

 install: @if [[ ! -x "$(shell command -v ghead)" ]]; then \ echo 'ghead does not exist. Please install it.'; \ exit -1; \ fi

Richard A Quadling

다음과 같이 더 간단할 수 있습니다.

 #!/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

foovi 로 변경하여 다른 조건이 실행되도록 합니다.


todd_dsm

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 executable 2 if an invalid option is specified

좋은 점에 대해 which 실행 파일이있는 환경에서 사용할 수있는 경우가 파악한다는 것입니다 which 에서 실행 - 그것은 몇 가지 문제를 저장 ...


Adam Davis

데비안 서버에 대한 내 설정:

여러 패키지에 같은 이름이 포함되어 있을 때 문제가 발생했습니다.

예를 들어 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 }

ThCTLo

너희들 / 여자들이 여기에서 답변을 얻을 수없고 머리카락을 뒤로 빼는 경우 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

user619271

프로그램이 존재하고 Bash 내장 명령이 아닌 프로그램인지 확인하려는 경우 command , typehash 는 모두 내장 명령에 대해 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

rpr

zsh 전용 zsh 스크립팅에 매우 유용합니다(예: 완료 스크립트 작성 시):

zsh/parameter 모듈은 무엇보다도 내부 commands 해시 테이블에 대한 액세스를 제공합니다. man zshmodules :

 THE ZSH/PARAMETER MODULE The zsh/parameter module gives access to some of the internal hash ta‐ bles used by the shell by defining some special parameters. [...] commands This array gives access to the command hash table. The keys are the names of external commands, the values are the pathnames of the files that would be executed when the command would be in‐ voked. Setting a key in this array defines a new entry in this table in the same way as with the hash builtin. Unsetting a key as in `unset "commands[foo]"' removes the entry for the given key from the command hash table.

zsh --emulate 와 함께 사용되지 않는 한 기본적으로 로드되는 것 같습니다.

예시:

 martin@martin ~ % echo $commands[zsh] /usr/bin/zsh

특정 명령을 사용할 수 있는지 빠르게 확인하려면 해시에 키가 있는지 확인하세요.

 if (( ${+commands[zsh]} )) then echo "zsh is available" fi

해시는 실행 가능 여부에 관계없이 $PATH 폴더에 있는 모든 파일을 포함합니다. 절대적으로 확신하려면 다음과 같이 stat 호출을 해야 합니다.

 if (( ${+commands[zsh]} )) && [[ -x $commands[zsh] ]] then echo "zsh is available" fi

Martin von Wittich

해시 변형에는 한 가지 함정이 있습니다. 예를 들어 명령줄에서 다음을 입력할 수 있습니다.

 one_folder/process

프로세스를 실행하도록 합니다. 이를 위해 one_folder 의 상위 폴더는 $PATH 에 있어야 합니다. 그러나 이 명령을 해시하려고 하면 항상 성공합니다.

 hash one_folder/process; echo $? # will always output '0'

anycast.cw

두 번째로 "command -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

user2961933

CI 서버 배포의 일부로 Git이 설치되었는지 확인해야 했습니다. 내 최종 Bash 스크립트는 다음과 같습니다(Ubuntu 서버).

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

Greg K

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

tim

type 명령을 사용할 수 없는 경우 (여기서 당연하게 간주됨) 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

최소한 Bash 4.2.24(2) command -v ls 사용하는 Mac OS X v10.6.8 /bin/ls-temp 와 일치하지 않습니다.


freno

출처 : http:www.stackoverflow.com/questions/592620/how-can-i-check-if-a-program-exists-from-a-bash-script

반응형