Linux 쉘 스크립트 : 존재하는 경우에만 프로그램을 실행하고 존재하지 않는 경우 무시하십시오.


15

적절한 도구 (예 : 시스템 경로에 도달 가능) 가 설치된 경우에만 실행 중에 상태 배너를 인쇄 하는 Linux 쉘 스크립트 를 프로그래밍 중 입니다. figlet

예:

#!/usr/bin/env bash
echo "foo"
figlet "Starting"
echo "moo"
figlet "Working"
echo "foo moo"
figlet "Finished"

나는 일에 나의 스크립트 싶습니다 오류없이 하는 경우도 figlet있다 설치되어 있지 .

무엇을 할 수있는 실제적인 방법 ?



@ sudodus : 'figlet'(및 해당 매개 변수) 명령을 무시하는 것이 좋습니다. 물론 계속되는 처형.
Sopalajo de Arrierez

2
이 질문에 대한 제목은 모든 종류의 형이상학 적 문제를 일으켰습니다
g_uint

2
모든 오류 를 무시 하시겠습니까? 그냥 사용하십시오 figlet ... || true.
Giacomo Alzetta

종료 코드에 신경 쓰지 않는다면 바로 가기를 사용하는 figlet || true것이 좋지만 귀하의 경우 배너를 인쇄 할 수없는 경우 일반 텍스트를 에코하는 쉘 기능이 더 적합합니다.
eckes

답변:


30

내 해석은 도구와 동일한 래퍼 함수를 ​​사용합니다. 해당 함수에서 실제 도구가 존재하면 실행하십시오.

figlet() {
  command -v figlet >/dev/null && command figlet "$@"
}

그러면 figlet arg1 arg2...스크립트에서 변경하지 않아도 됩니다.

@Olorin은 더 간단한 방법을 찾았습니다. 필요한 경우에만 도구를 정의하십시오 (도구가 존재하지 않는 경우).

if ! command -v figlet > /dev/null; then figlet() { :; }; fi

figletfiglet이 설치되지 않은 경우에도 인수를 인쇄하려면 다음과 같이 Olorin의 제안을 조정하십시오.

if ! command -v figlet > /dev/null; then figlet() { printf '%s\n' "$*"; }; fi

1
어디 command에서 왔습니까? 설치에 포함되어 있지 않습니다 (Red Hat 6.8 Enterprise 및 Cygwin64).
eewanco

1
@eewanco 참조 unix.stackexchange.com/a/85250/117549 ; 간단히 말해서, 그것은 bash에 내장되어 있으며 아마도 껍질 일 것입니다.
Jeff Schaller

4
commandPOSIX Bourne 쉘 내장입니다. 일반적으로 제공된 명령을 실행하지만 -v플래그는 type다른 쉘 내장 과 비슷하게 동작합니다 .
wyrm

@eewanco type -a command가 보여줄 것입니다. which것입니다 온 실행 표시 $PATH하지 내장 기능, 키워드, 함수 또는 별칭을.
l0b0

@ l0b0 : bash는 기본 프로파일 (들)과 레드햇 - 가족 which 않습니다 이 별칭 때문에, 적용 가능한 별칭을 찾아 which실행 자체를 /usr/bin/which(!)와 파이프가의 모습 셸의 별칭 목록은 (물론 \which별칭을 억제 별명을 표시하지 않는 프로그램 만 사용합니다.)
dave_thompson_085

14

figlet존재 하는지 테스트 할 수 있습니다

if type figlet >/dev/null 2>&1
then
    echo Figlet is installed
fi

6

이 작업을 수행하는 일반적인 방법은 test -x일명 [ -x입니다. 다음은 /etc/init.d/ntpLinux 시스템 에서 가져온 예입니다 .

if [ -x /usr/bin/lockfile-create ]; then
    lockfile-create $LOCKFILE
    lockfile-touch $LOCKFILE &
    LOCKTOUCHPID="$!"
fi

이 변형은 실행 파일의 전체 경로를 알고 있어야합니다. 에서 와 명령 /bin/lesspipe을 결합하여 그 문제를 해결하는 예제를 찾았습니다 .-xwhich

if [ -x "`which bunzip`" ]; then bunzip -c "$1"
else echo "No bunzip available"; fi ;;

그렇게 PATH하면 bunzip실행 파일의 위치를 미리 알지 않고도 작동 합니다.


4
를 사용하지 마십시오which . 그리고 which작동 하더라도 test -x출력을 사용 하는 것은 바보입니다 :에서 경로를 얻는다면 which존재합니다.
질 'SO-정지 존재 악마'

1
@Gilles : 기술적으로 말해서, test -x파일이 존재하는지 확인하는 것 이상의 의미를 지닙니다 test -e. 또한 파일에 실행 권한이 설정되어 있는지 확인합니다.
comfreak

@comfreak 그렇습니다 which.
Gilles 'SO- 악마 그만

5

스크립트를 시작할 때 figlet존재 하는지 확인하고 존재하지 않는 경우 아무 것도 수행하지 않는 쉘 함수를 정의하십시오.

type figlet >/dev/null 2>&1 || figlet() { :; }

typefiglet쉘 내장, 함수, 별명 또는 키워드로 존재 하는지 확인하고 >/dev/null 2>&1stdin 및 stdout을 버리고 출력을 얻지 못하고 존재하지 않는 경우 figlet() { :; }정의합니다.figlet 아무것도하지 않는 함수로 .

이런 식으로을 사용하는 스크립트의 모든 줄을 편집 figlet하거나 매번 존재하는지 확인할 필요가 없습니다.figlet 호출 .

원하는 경우 진단 메시지를 추가 할 수 있습니다.

type figlet >/dev/null 2>&1 || { echo 'figlet not installed.' ; figlet() { :; } ; }

보너스로, 어떤 쉘을 사용하고 있는지 언급하지 않았으므로 POSIX와 호환되므로 대부분의 쉘에서 작동해야합니다.


나는이 대답의 단순함을 좋아한다. bash를 사용 type figlet >/dev/null 2>&1하는 hash figlet 2>/dev/null경우 에도 바꿀 수 있습니다 . (OP가 "내 경로에 있다면"이라고 말했다.)
Joe

5

또 다른 대안은 프로젝트 자동 구성 스크립트에서 본 패턴입니다.

if [ -x /usr/bin/figlet ]
then
    FIGLET=/usr/bin/figlet
else
    FIGLET=:
fi

$FIGLET "Hello, world!"

특정한 경우에는 할 수도 있습니다.

if [ -x /usr/bin/figlet ]
then
   SAY=/usr/bin/figlet
elif [ -x /usr/local/bin/figlet ]
then
   SAY=/usr/local/bin/figlet
elif [ -x /usr/bin/banner ]
then
   SAY=/usr/bin/banner
else
   SAY=/usr/bin/echo
fi

$SAY "Hello, world!"

특정 경로를 모르는 경우 여러 위치 elif(위 참조)를 사용하여 알려진 위치를 시도하거나를 사용하여 PATH항상 명령을 해결할 수 있습니다.

if command -v figlet >/dev/null
then
    SAY=figlet
elif command -v banner >/dev/null
then
    SAY=banner
else
    SAY=echo
fi

일반적으로 스크립트를 작성할 때 본인이 지정한 특정 위치에서만 명령을 호출하는 것을 선호합니다. 나는 최종 사용자가 자신의에 넣어 수도 무슨의 불확실성 / 위험 좋아하지 않는다 PATH아마도 자신에 ~/bin.

예를 들어, 내가 호출하는 특정 명령의 출력을 기반으로 파일을 제거 할 수있는 다른 사람들을 위해 복잡한 스크립트를 작성하는 경우 실수로 ~/bin명령에서 또는 명령이 아닐 수있는 무언가를 선택하고 싶지 않습니다. 기대했다.


3
어떤 경우 figlet에 있었다 /usr/local/bin/home/bob/stuff/programs/executable/figlet?
Gilles 'SO- 악의를 멈추십시오'

3
type -p figlet > /dev/null && figlet "foo"

bash type명령은 명령, 함수, 별명, 키워드 또는 내장을 찾고 (참조 help type) 위치 또는 정의를 인쇄합니다. 또한 검색 결과를 나타내는 리턴 코드를 리턴합니다. 발견되면 true (0). 그래서 우리가 여기서하고있는 일은 figlet경로에서 찾으려고 노력하는 것 입니다 ( -p내장 또는 함수가 아닌 파일을 찾고 오류 메시지를 억제 함을 > /dev/null의미합니다 &&). 실행됩니다figlet 됩니다.

figlet고정 된 위치에 있으면 더 간단합니다 .

[ -x /usr/bin/figlet ] && /usr/bin/figlet "foo"

여기서 우리는 test명령 (aka [)을 사용하여 /usr/bin/figlet실행 가능한지 ( -x) 확인하고 그렇다면 ( &&) 실행하는지 확인합니다. 이 솔루션은 사용하는 것보다 이식성이 뛰어납니다.type 하는 bashism 인 뛰어납니다.

이를 위해 다음과 같은 기능을 수행 할 수 있습니다.

function x() {
    if type -p "$1" >/dev/null; then
        cmd="$1"
        shift
        "$cmd" "$@"
    fi
}

(잠재적 인 공간 때문에 따옴표가 필요합니다)

그럼 당신은 할 것입니다 :

x figlet "foo"

0

o /, 나는 다음과 같이 말할 것이다

#!/usr/bin/env bash
# if figlet is installed :
if [ "$(which figlet 2>/dev/null)" ]; then
       # do what you wanted to do
       echo "foo"
       figlet "Starting"
       echo "moo"
       figlet "Working"
       echo "foo moo"
       figlet "Finished"
# if not
else
       # exit program with an error
       echo "please install figlet"
       exit 1
fi

0

테스트 실행, 출력 억제 및 테스트 성공 / 실패 코드를 수행 할 수 있습니다. 이 테스트를 저렴하게하려면 figlet에 대한 인수를 선택하십시오. -? 또는 --help 또는 --version이 확실한 가능성입니다.

if figlet --help >/dev/null 2>&1 ; then
    # figlet is available
    echo "foo"
    figlet "starting"
    #etc
else
    rc=$?
    echo "figlet is not installed or not working correctly (return code ${rc})"
fi

아래 주석에 대한 응답으로 추가 : 당신이 실제로 사용 가능한지 아닌, 작은 그림이 존재하는지 테스트하고 싶다면, 당신은 할 것입니다

figlet --help >/dev/null 2>&1 
rc=$?
if [ $rc -eq 127 ] ; then # 127 is "command not found" on linux bash 4.4.23(1)
    echo "command figlet not found"
else
    figlet "whatever" # use figlet
fi

여기서 문제는 figlet이 설치되지 않은 것 이외의 이유로 실패 할 수 있으므로 종료 코드를 테스트하는 것만으로는 충분하지 않다는 것입니다.
Chris

설치 만 테스트하고 싶다면 $?127 (내 리눅스 시스템에서)과 같은지 테스트하고 싶습니다 . 127은 "명령을 찾을 수 없습니다"입니다. 그러나 내 생각은 합리적 명령의 경우 command --help실패하면 설치가 충분하지 않아 충분히 설치되지 않은 것입니다!
nigel222

1
126은 "명령을 찾았지만 실행할 수 없습니다"이므로 이에 대해서도 테스트하려고합니다. 불행히도, 당신은 의지 할 수 없습니다--help . Posix 유틸리티는이를 가지고 있지 않으며 posix 지침은 실제로 권장 하지 않습니다 . 예를 들어 내 시스템에서 종료 상태로 at --help실패 합니다. at: invalid option -- '-'130
Chris

물론, 만일 figlet이 상태 127로 빠져 나갈 수 있다면 그것은 역시 문제가 될 수 있습니다.
Chris

(126)에 대한 공정 점 대부분의 제정신 유틸리티는 다음과 같은 경량 무해한 명령 옵션의 일종이 -? --help --version... 당신이 무엇을 찾을 수있는 또는 figlet -0 --illegal이 아니라 127의 한으로 (당신의 성공 지표로로 종료하고 치료하는 내가 클래스는 것을 방해 행위로).
nigel222
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.