programing

Bash 스크립트에서 프로그램이 존재하는지 확인하려면 어떻게 해야 합니까?

powerit 2023. 4. 19. 00:32
반응형

Bash 스크립트에서 프로그램이 존재하는지 확인하려면 어떻게 해야 합니까?

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

쉬워야 할 것 같은데 자꾸 날 당황하게 해.

정답.

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 쉘이 POSIX 쉘에 대해 이 을 수행하는 ).hash
  • many many를 만듭니다.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에 쓰려고 할 때 프로그램에서 오류가 발생합니다. 이는 FD 2에 성공적으로 쓰거나 출력을 폐기하는 것과는 매우 다릅니다(그리고 위험합니다!).

'해'인 /bin/sh「POSIX」입니다. type ★★★★★★★★★★★★★★★★★」hashPOSIX POSIX에 않습니다.hash 때(이되지 않습니다)는됩니다.typecommand의 종료 상태는 POSIX에 의해 잘 정의되어 있기 때문에 가장 안전한 것이 될 수 있습니다.

에 「」가 사용되고 있는 .bash POSIX 은 더 둘 다 중요하지 않다.type ★★★★★★★★★★★★★★★★★」hash안전하게 사용할 수 있게 됩니다. type이 시점에서-PPATH ★★★★★★★★★★★★★★★★★」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."

가 에 할 수 휴대용 방법입니다.$PATH 실행 가능:

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

예:

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

가능 는 실행 을 반환하기 필요합니다.이러한 이름의 이 bash에 이름의 실행 가능 파일이 는 실행 하기 때문입니다.$PATH.

또한 실행 파일과 이 이전에 해 주십시오.$PATH, dash는 후자가 실행되더라도 전자를 반환합니다.이는 버그로 POSIX 규격에 위배됩니다.[버그리포트] [표준]
편집: 이것은 대시 0.5.11(데비안 11)에서 수정되었습니다.

또한 찾고 있는 명령어가 에일리어스로 정의되어 있는 경우 이 작업은 실패합니다.

는 lhunath의 합니다.which그리고 그의 솔루션은 Bash 사용자에게 완벽하게 유효합니다.하지만 좀 더 휴대하기 쉽도록command -v츠키다

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

「」command는 POSIX에 준거하고 있습니다.자세한 내용은 여기를 참조하십시오: command - execute a simple command

★★★★★★type준거하고 만, POSIX는 POSIX에 준거하고 있습니다.type -P렇지않않 않않않다다

디렉토리가 이 에 있는지 알고 에 따라 .$PATH변수 또는 변수의 절대 위치를 알고 있는지 여부를 지정합니다.이 에 $PATH, use, use

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/에서는 첫 in 、 of of of of of of の of of of of of of of의 출력을 하고 있습니다.which프로그램.

.bashrc에 정의되어 있는 함수가 있습니다.

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

들어 다음과 .bash_profile

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

@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

사용 방법:

test -x filename

또는

[ -x filename ]

[ Conditional Expressions ]의 [Bash]맨 페이지에서 다음 순서를 수행합니다.

 -x file
          True if file exists and is executable.

「」를 hash@lhunath가 시사하는 바와 같이 Bash 스크립트로 다음 작업을 수행합니다.

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

이 스크립트는 실행됩니다.hash 코드, 에 저장되어 값, 에 저장되어 있는 확인합니다.$?는 , , , , , , 입니다.1.hash 수 없다foo는 '출구 코드'가 됩니다1.foo종료 는 """입니다.0.

&> /dev/null표준 에러와 표준 출력을 리다이렉트 합니다.hash에 되지 않도록 ★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★」echo >&2는 표준 에러에 메시지를 씁니다.

「」-v이 POSIX_BUILTINS로 경우 합니다.<command>년 가 없는

다음 사항이 장애 발생 가능성이 더 높습니다.

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

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

프로그램이 존재하는지 확인하면 나중에 실행할 수 있습니다.애초에 실행해 보지 그래요?

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

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

또한 프로그램에서 버전 등 유용한 결과를 얻을 수 있습니다.

도 있고 시작하기에 너무 많은 프로그램도 있고, 시작하기에 너무 프로그램이.--version옵션을 사용하여 즉시(및 정상적으로) 종료할 수 있습니다.

여기에는 많은 선택사항이 있지만, 나는 짧은 단도직입적인 답변이 없다는 것에 놀랐다.스크립트의 처음에 사용한 것은 다음과 같습니다.

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

이는 여기서 선택한 답변과 다른 소스를 기반으로 합니다.

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

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-get 패키지가 설치되어 있는지 확인하고 Linux에 설치되어 있지 않은 경우 설치합니다.

앞서 "Bash 스크립트에서 프로그램이 존재하는지 확인하는 방법"에서 언급했습니다.

제가 접근할 수 있는 박스에 대한 이전 답변을 얻지 못했습니다.for for fortype가 인스톨 되고 있습니다(실행하고 있습니다).따라서 기본 제공 지침이 필요합니다.이 명령어는 나에게 유효합니다.

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

Make file 내에서 실행되도록 동일한 질문에 답변하고 싶었습니다.

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

좀 더 심플할 수도 있어요.

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

foo로로 합니다.vi다른 조건이 발화되도록 하기 위해서요

hash foo 2>/dev/null: Z 쉘(Zsh), Bash, Dash Ash와 함께 작동합니다.

type -p foo: Z 쉘, Bash 및 ash(Busy Box)에서는 동작하지만 대시(해석)에서는 동작하지 않습니다.-p( 로た )

command -v fooZBox Z 、 Bash 、 Dash 、 Busy Box )에서는합니다.-ash: command: not found를 참조해 주세요.

, 「 」, 「 」라고 하는 도 주의해 주세요.builtin및 Dashash Dash에는 할 수 .

zsh 한정되어 있지만, 매우 편리합니다.zsh"CHANGE: "CHANGE: "CHANGE: "CHANGE: "CHANGE: "CHANGE: "CHAN

zsh/parameter ''을 할 수 .commands터터 from터터터부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

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몇 가지 문제를 줄일 수 있습니다.

이미 설치된 라이브러리를 감지하려면 이전 답변의 방법론 중 아무 것도 작동하지 않습니다.패스를 물리적으로 체크하는 것(헤더 파일등의 가능성이 있다), 또는 다음과 같은 것(Debian 베이스의 디스트리뷰션의 경우)이 남았을 것입니다.

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

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

위에서 알 수 있듯이 쿼리의 "0" 응답은 패키지가 설치되지 않았음을 의미합니다.이것은 "grep"의 함수입니다. "0"은 일치를, "1"은 일치를 찾을 수 없음을 나타냅니다.

가능한 경우 Bash 빌트인 사용:

which programname

...

type -P programname

프로그램의 유무에 따라, 다음의 정보가 표시됩니다.

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

매달려서 휴대성이 뛰어나고 100% 신뢰할 수 있는 방법은 없다고 생각합니다.alias. §:

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

물론, 마지막 한 가지만 문제가 있다(링고에게 불쾌감을 주는 것은 아니다!). 모두 합니다.aliascommand -v.

매달리는 걸 거부하기 위해서ringo 내장된 alias 및 명령어)command -valias여기). 휴대용 솔루션은 없습니다.부끄럼을 참다

은 무조건 하시기 바랍니다.alias ls='ls -F':

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

안 , 이 를 사용해서 같은 .bash -c$(.$(하위 명령)를 실행하면 실제로 다음과 같은 일이 발생합니다.

첫째, 완전히 다른 결과를 얻을 수 있습니다.

$ 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
#!/bin/bash
a=${apt-cache show program}
if [[ $a == 0 ]]
then
echo "the program doesn't exist"
else
echo "the program exists"
fi

#프로그램은 리터럴이 아닙니다.확인할 프로그램 이름으로 변경할 수 있습니다.

해시 변수에는 다음 1개의 함정이 있습니다.명령줄에서 예를 들어 다음과 같이 입력할 수 있습니다.

one_folder/process

프로세스를 실행할 수 있습니다.이를 위해서는 one_folder의 부모 폴더가 $PATH에 있어야 합니다.단, 이 명령어를 해시하려고 하면 항상 성공합니다.

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

나는 "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

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

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

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

typePOSIX 준거 명령어를 사용할 수 있습니다(여기에서는 당연시되고 있습니다).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

적어도 Mac OS X v10.6.8(Snow Leopard)에서 Bash 4.2.24 (2)를 사용하는 경우command -v ls하지 않습니다./bin/ls-temp.

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
}

언급URL : https://stackoverflow.com/questions/592620/how-can-i-check-if-a-program-exists-from-a-bash-script

반응형