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
★★★★★★★★★★★★★★★★★」hash
POSIX POSIX에 않습니다.hash
때(이되지 않습니다)는됩니다.type
command
의 종료 상태는 POSIX에 의해 잘 정의되어 있기 때문에 가장 안전한 것이 될 수 있습니다.
에 「」가 사용되고 있는 .bash
POSIX 은 더 둘 다 중요하지 않다.type
★★★★★★★★★★★★★★★★★」hash
안전하게 사용할 수 있게 됩니다. type
이 시점에서-P
PATH
★★★★★★★★★★★★★★★★★」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 foo
ZBox 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
실행 파일이 발견되면 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=/
물론, 마지막 한 가지만 문제가 있다(링고에게 불쾌감을 주는 것은 아니다!). 모두 합니다.alias
command -v
.
매달리는 걸 거부하기 위해서ringo
내장된 alias
및 명령어)command -v
alias
여기). 휴대용 솔루션은 없습니다.부끄럼을 참다
은 무조건 하시기 바랍니다.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; }
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
적어도 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
'programing' 카테고리의 다른 글
Bash에서 파일을 효율적으로 변환하는 방법 (0) | 2023.04.19 |
---|---|
Tree View 전체를 강조 표시WPF의 항목 행 (0) | 2023.04.19 |
MVVM을 통한 적절한 검증 (0) | 2023.04.19 |
사용자 선택 범위 가져오기 (0) | 2023.04.19 |
Excel의 .xlsx XML 형식에 대한 명확한 설명을 찾고 있습니다. (0) | 2023.04.19 |