명령이 성공 또는 실패한 경우 조건부로 작업을 수행하는 방법


283

bash에서 어떻게 이런 일을 할 수 있습니까?

if "`command` returns any error";
then
    echo "Returned an error"
else
    echo "Proceed..."
fi

답변:


359

명령이 성공 또는 실패한 경우 조건부로 작업을 수행하는 방법

bash의 if진술은 정확히 다음과 같습니다.

if command ; then
    echo "Command succeeded"
else
    echo "Command failed"
fi

주석에서 정보 추가 : 이 경우 에는 ... 구문 을 사용할 필요 가 없습니다 . 자체는 명령과 거의 동일합니다 . 에서 사용하는 가장 일반적인 명령 일 수 있으며 , 이는 쉘 구문의 일부라는 가정으로 이어질 수 있습니다. 그러나 명령의 성공 여부를 테스트하려면 위에 표시된대로 명령 자체를 직접 사용하십시오 .[][testifif

편집 : 명확성을 위해 상단에 질문을 인용했습니다 (이 답변은 페이지 상단 근처에 나타나지 않습니다).


11
세미콜론이 중요합니다.
Thorbjørn Ravn Andersen

21
또는 then별도의 줄에 넣을 수 있습니다 .
l0b0

36
@ 조 : 나는 당신이 의미하는 것 같아요 if ! command ; then ... ; fi. [그 자체가 명령이며,이 경우에는 필요하지 않습니다.
Keith Thompson

20
@ 조 : 내 방식은 또한 덕목이 있습니다. if [ ! command ]실행하지 않습니다 command. 그것은 취급 command문자열로하고 같은 사실이 0이 아닌 길이를 가지고 있기 때문에 취급합니다. [동의어입니다 test명령
키이스 톰슨

5
죄송합니다. 당신은 맞습니다.
Joe

133

쉘 명령이 작동하면 작은 일이 발생하면 &&구문을 사용할 수 있습니다 .

rm -rf somedir && trace_output "Removed the directory"

셸 명령이 실패했을 때 발생하는 작은 일에 대해서도 마찬가지로 다음을 사용할 수 있습니다 ||.

rm -rf somedir || exit_on_error "Failed to remove the directory"

아니면 둘다

rm -rf somedir && trace_output "Removed the directory" || exit_on_error "Failed to remove the directory"

아마도 이러한 구성으로 많은 것을 수행하는 것은 현명하지 않지만 때로는 제어 흐름을 훨씬 명확하게 만들 수 있습니다.


3
그것들은 더 짧고 (적어도 일부 껍질에서는) 더 빠릅니다. 나는 한 번 해독하려고했던 이러한 조건부 구성으로 작성된 몬스터 Ultrix 설치 스크립트를 기억하고
떨었습니다

101

$?가장 최근의 명령 / 기능을 실행 한 결과를 포함하는 의 값을 확인하십시오 .

#!/bin/bash

echo "this will work"
RESULT=$?
if [ $RESULT -eq 0 ]; then
  echo success
else
  echo failed
fi

if [ $RESULT == 0 ]; then
  echo success 2
else
  echo failed 2
fi

11
기술적으로 정확하지만 (공개를 보증하지 않음) Bash의 if관용구를 사용하지 않습니다 . Keith Thompson의 답변을 선호합니다.
janmoesen

16
이 관용구에는 이점이 있습니다-반환 값을 유지합니다. 결국, 나는 이것이 더 강력하지만 더 강력하다는 것을 알았습니다. 또한 읽기가 더 쉽습니다.
taxilian

2
"이디엄의 배쉬"는 무엇입니까?
Nowaker 2018 년

3
@Nowaker 유일한 목적은 if이 작업을 수행하는 것입니다. Bash의 흐름 제어 조건은 모두 $?뒤에서 검사 합니다. 그것이 그들이하는 일입니다. 대부분의 경우 명시 적으로 그 가치를 검사하는 것은 불필요해야하며 일반적으로 초급 반 패턴입니다.
tripleee

1
@lunakid 종료 코드에 신경 쓰지 않는다면 if ! cmd괜찮습니다. 그렇지 않으면 일반적인 배열은 else절 을 사용하는 것 입니다. 빈 칸을 가질 수는 없지만 then때로는 no-op가 중요한 then : nothing; else곳을 볼 수 있습니다 :. true거기에서도 작동합니다.
트리플 리

47

이것은 나를 위해 일했다 :

command && echo "OK" || echo "NOK"

경우는 command다음 성공적으로 echo "OK"실행되고, 그 성공 이후, 실행이 중지됩니다. 그렇지 않으면 &&건너 뛰어 echo "NOK"실행됩니다.


5
실패한 경우 무언가를하고 종료 코드를 유지하려면 (명령 프롬프트에 표시하거나 스크립트로 테스트) 다음과 같이하십시오. command && echo "OK" || c=$?; echo "NOK"; $(exit $c)
Sam Hasler

2
@ Sam-Hasler : 그렇지 command && echo "OK" || (c=$?; echo "NOK"; (exit $c))않습니까?
jrw32982

9
또한 echo "OK"부품 자체가 고장날 수있는 경우 더 좋습니다.command && (echo "OK"; exit 0) || (c=$?; echo "NOK"; (exit $c))
jrw32982

@ jrw32982, Nice, 나는 이전 구성을 사용했지만 후자는 사용하지 않았습니다.
Sam Hasler

실제 답변은 의견에 있습니다. 모두 감사합니다!
Joshua Pinter

6

접근의 유형 if...then...fi&&/ 또는 ||유형은 우리가 테스트하고자하는 명령에 의해 종료 된 종료 상태를 처리 한다는 점에 유의해야합니다 (성공시 0). 그러나 일부 명령은 명령이 실패했거나 입력을 처리 할 수없는 경우 0이 아닌 종료 상태를 리턴하지 않습니다. 이것은 일반적인 명령 if&&/ ||접근 방식이 특정 명령에 대해 작동하지 않음을 의미 합니다.

예를 들어, Linux file에서 존재하지 않는 파일을 인수로 받고 find지정된 파일 사용자를 찾을 수없는 경우 GNU는 여전히 0으로 종료 됩니다.

$ find . -name "not_existing_file"                                          
$ echo $?
0
$ file ./not_existing_file                                                  
./not_existing_file: cannot open `./not_existing_file' (No such file or directory)
$ echo $?
0

이러한 경우 상황을 처리 할 수있는 잠재적 인 방법 중 하나는 stderr/ stdin메시지 file와 같이 명령에 의해 반환 된 메시지를 읽거나와 같이 명령 출력을 구문 분석하는 것입니다 find. 이를 위해 case진술을 사용할 수 있습니다.

$ file ./doesntexist  | while IFS= read -r output; do                                                                                                                  
> case "$output" in 
> *"No such file or directory"*) printf "%s\n" "This will show up if failed";;
> *) printf "%s\n" "This will show up if succeeded" ;;
> esac
> done
This will show up if failed

$ find . -name "doesn'texist" | if ! read IFS= out; then echo "File not found"; fi                                                                                     
File not found

2

내가 일으킬 수있는 가장 오류가 발생하기 쉬운 것은 다음과 같습니다.

  • 먼저 가치를 얻으십시오. 다음과 같은 일을한다고 가정하십시오.

RR=$?

이제이 상황뿐만 아니라 다른 사람들이 직면 할 수도있는 사항을 고려하십시오.

정의 된 변수 :

$ AA=1 ; if (( "10#0${AA}" == 1 )) ; then echo yes ; else echo no ; fi

답 : 예

$ AA=1 ; if (( "10#0${AA}" != 1 )) ; then echo yes ; else echo no ; fi

답변 : 아니오

정의되지 않은 변수:

$ AA=1 ; if (( "10#0${BB}" == 1 )) ; then echo yes ; else echo no ; fi

답변 : 아니오

$ AA=1 ; if (( "10#0${BB}" != 1 )) ; then echo yes ; else echo no ; fi

답 : 예

$ AA=1 ; if (( "10#0${BB}" == 0 )) ; then echo yes ; else echo no ; fi

답 : 예

이것은 모든 종류의 오류를 방지합니다.

모든 구문을 알고 있을지 모르지만 여기에 몇 가지 팁이 있습니다.

  • 따옴표를 사용하십시오. A는 피 "blank"nothing.
  • 변수에 대한 새로운 현대 표기법은 ${variable}입니다.
  • 숫자 앞에 0을 추가하면 "아무 숫자도"피합니다.
  • 그러나 0을 추가하면 숫자가 base-8됩니다. 다음과 같은 오류가 발생합니다.
    • value too great for base (error token is "08")위의 숫자 7. 그때가 시작됩니다 10#.
    • 10#숫자를 강제로합니다 base-10.

1

당신은 이것을 할 수 있습니다 :

if ($( ping 4.4.4.4 -c1 > /dev/null )) ; then
  echo "ping response succsess!!!"
fi

9
그것은 효과가 있지만 복잡합니다. 서브 쉘의 서브 쉘에서 ping ping을 실행 중이며, 명령으로 실행하는 관점에서 출력 이 캡처됩니다. 그러나 출력이 / dev / null로 리디렉션되기 때문에 항상 빈 문자열이됩니다. 따라서 서브 쉘에서 아무것도 실행하지 않습니다. 즉, 이전 대체 상태 (명령 대체 서브 쉘, 즉 ping)가 유지됩니다. 분명히 올바른 방법이 if ping ...; then여기 있습니다.
Stéphane Chazelas

1

이 글의 다른 부분에서 언급했듯이, 원래의 질문은 기본적으로 스스로 대답합니다. 다음은 if조건이 중첩 될 수 있음을 보여주는 그림 입니다.

이 예제는 if파일이 존재하고 일반 파일인지 확인하는 데 사용 합니다. 이러한 조건이 충족되면 크기가 0보다 큰지 여부를 확인하십시오.

#!/bin/bash

echo "Which error log are you checking today? "
read answer

if [ -f /opt/logs/$answer*.errors ]
    then
        if [ -s /opt/logs/$answer*.errors ]
            then
                echo "Content is present in the $answer error log file."
            else
                echo "No errors are present in the $answer error log file."
        fi
    else
        echo "$answer does not have an error log at this time."
fi

2
그것이 당신의 대답이지만, 당신의 대답은 그 질문을 다루지 않습니다.
Jeff Schaller

@ JeffSchaller 감사합니다. 질문에 대한 참조를 포함하도록 게시물을 편집했습니다.
quartzinquartz

1
#!/bin/bash

if command-1 ; then
   echo "command-1 succeeded and now running from this block command-2"
   command-2
else
   echo "command-1 failed and now running from this block command-3"
   command-3
fi

3
이것은 기존의 허용 된 답변 과 매우 비슷합니다 . 제발 속성 은 재사용하고 일을하거나 답변에 자신의 노력을 추가합니다.
Jeff Schaller

-3

이것은 $?마지막으로 실행 된 명령의 상태를 제공하는 방식으로 간단하게 수행 할 수 있습니다 .

그래서 그것은 될 수 있습니다

#!/bin/sh

... some command ...

if [ $? == 0 ] ; then
  echo '<the output message you want to display>'
else 
  echo '<failure message>'
fi

1
공감 : 이것은 단순히 단 항적이라는 비판을받은 이전의 대답을 간단히 말로 표현합니다.
tripleee
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.