[shell] 프로세스의 반환 값을 어떻게 부정 할 수 있습니까?

프로세스가 반환하는 값을 부정 하는 단순하지만 크로스 플랫폼 부정 프로세스를 찾고 있습니다. 0을 어떤 값으로 매핑해야합니다! = 0 및 모든 값을! = 0에서 0으로 매핑해야합니다. 즉, 다음 명령은 “예, 존재하지 않는 경로가 존재하지 않습니다”를 반환해야합니다.

 ls nonexistingpath | negate && echo "yes, nonexistingpath doesn't exist."

! -연산자는 훌륭하지만 안타깝게도 셸에 독립적이지 않습니다.



답변

이전에는 마지막 섹션으로 현재 첫 번째 섹션이 무엇인지 대답이 제시되었습니다.

POSIX Shell에는 !연산자가 포함되어 있습니다.

다른 문제에 대한 셸 사양을 살펴보면서 최근 (2015 년 9 월) POSIX 셸이 !연산자를 지원한다는 것을 알았습니다 . 예를 들어, 예약어 로 나열되고 파이프 라인 의 시작 부분에 나타날 수 있습니다. 여기서 간단한 명령은 ‘pipeline’의 특별한 경우입니다. 따라서 POSIX 호환 셸 에서 if문 및 while/ 또는 until루프에서도 사용할 수 있습니다 . 결과적으로 내 예약에도 불구하고 2008 년에 깨달은 것보다 더 널리 사용 가능할 것입니다. POSIX 2004 및 SUS / POSIX 1997을 빠르게 확인하면 !두 버전 모두에 존재 하는 것으로 나타났습니다 .

점을 유의 !운영자가에 나타나야 시작 파이프 라인의 전체 파이프 라인의 상태 코드 (즉, 부정 마지막 명령). 여기 예시들이 있습니다.

# Simple commands, pipes, and redirects work fine.
$ ! some-command succeed; echo $?
1
$ ! some-command fail | some-other-command fail; echo $?
0
$ ! some-command < succeed.txt; echo $?
1

# Environment variables also work, but must come after the !.
$ ! RESULT=fail some-command; echo $?
0

# A more complex example.
$ if ! some-command < input.txt | grep Success > /dev/null; then echo 'Failure!'; recover-command; mv input.txt input-failed.txt; fi
Failure!
$ ls *.txt
input-failed.txt

휴대용 대답-골동품 조개와 함께 작동

Bourne (Korn, POSIX, Bash) 스크립트에서 다음을 사용합니다.

if ...command and arguments...
then : it succeeded
else : it failed
fi

이것은 휴대 성이 뛰어납니다. ‘명령 및 인수’는 파이프 라인 또는 기타 복합 명령 시퀀스 일 수 있습니다.

not명령

‘!’ 연산자는 쉘에 내장되어 있든 운영 체제에서 제공하든 보편적으로 사용할 수 없습니다. 하지만 작성하기가 끔찍하게 어렵지는 않습니다. 아래 코드는 최소한 1991 년으로 거슬러 올라갑니다 (나는 이전 버전을 더 오래 전에 작성했다고 생각하지만). 나는 안정적으로 사용할 수 없기 때문에 스크립트에서 이것을 사용하지 않는 경향이 있습니다.

/*
@(#)File:           $RCSfile: not.c,v $
@(#)Version:        $Revision: 4.2 $
@(#)Last changed:   $Date: 2005/06/22 19:44:07 $
@(#)Purpose:        Invert success/failure status of command
@(#)Author:         J Leffler
@(#)Copyright:      (C) JLSS 1991,1997,2005
*/

#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include "stderr.h"

#ifndef lint
static const char sccs[] = "@(#)$Id: not.c,v 4.2 2005/06/22 19:44:07 jleffler Exp $";
#endif

int main(int argc, char **argv)
{
    int             pid;
    int             corpse;
    int             status;

    err_setarg0(argv[0]);

    if (argc <= 1)
    {
            /* Nothing to execute. Nothing executed successfully. */
            /* Inverted exit condition is non-zero */
            exit(1);
    }

    if ((pid = fork()) < 0)
            err_syserr("failed to fork\n");

    if (pid == 0)
    {
            /* Child: execute command using PATH etc. */
            execvp(argv[1], &argv[1]);
            err_syserr("failed to execute command %s\n", argv[1]);
            /* NOTREACHED */
    }

    /* Parent */
    while ((corpse = wait(&status)) > 0)
    {
            if (corpse == pid)
            {
                    /* Status contains exit status of child. */
                    /* If exit status of child is zero, it succeeded, and we should
                       exit with a non-zero status */
                    /* If exit status of child is non-zero, if failed and we should
                       exit with zero status */
                    exit(status == 0);
                    /* NOTREACHED */
            }
    }

    /* Failed to receive notification of child's death -- assume it failed */
    return (0);
}

명령 실행에 실패하면 실패의 반대 인 ‘성공’을 반환합니다. 우리는 ‘아무것도 성공적으로하지 않음’옵션이 옳았는지 토론 할 수 있습니다. 아무것도 요청하지 않으면 오류를보고해야 할 수도 있습니다. ‘ "stderr.h"‘ 의 코드 는 간단한 오류보고 기능을 제공합니다. 저는 모든 곳에서 사용합니다. 요청시 소스 코드-저에게 연락하려면 내 프로필 페이지를 참조하십시오.


답변

Bash에서는! 명령 전에 연산자. 예를 들면 :

! ls nonexistingpath && echo "yes, nonexistingpath doesn't exist"


답변

시도해 볼 수 있습니다.

ls nonexistingpath || echo "yes, nonexistingpath doesn't exist."

또는 그냥 :

! ls nonexistingpath


답변

셸로 Bash가없는 경우 (예 : git 스크립트 또는 puppet exec 테스트) 다음을 실행할 수 있습니다.

echo '! ls notexisting' | bash

-> retcode : 0

echo '! ls /' | bash

-> retcode : 1


답변

! ls nonexistingpath && echo "yes, nonexistingpath doesn't exist."

또는

ls nonexistingpath || echo "yes, nonexistingpath doesn't exist."


답변

참고 : 때때로 !(command || other command).
여기 ! ls nonexistingpath && echo "yes, nonexistingpath doesn't exist."로 충분합니다.
서브 쉘이 필요 없습니다.

Git 2.22 (2019 년 2 분기)는 다음과 같은 더 나은 형태를 보여줍니다.

커밋 74ec8cf , commit 3fae7ad , commit 0e67c32 , commit 07353d9 , commit 3bc2702 , commit 8c3b9f7 , commit 80a539a , commit c5c39f4 (13 Mar 2019) by SZEDER Gábor ( szeder) .
참조 99e37c2 커밋 , 9f82b2a 커밋 , 900721e 커밋 에 의해 (2019년 3월 13일) 요하네스 Schindelin을 ( dscho) .
(Merged by Junio ​​C gitsterHamano in commit 579b75a , 25 Apr 2019)

t9811-git-p4-label-import: 파이프 라인 부정 수정

t9811-git-p4-label-import.sh‘에서 ‘ ‘테스트 tag that cannot be exported가 실행됩니다.

!(p4 labels | grep GIT_TAG_ON_A_BRANCH)

주어진 문자열이 ‘ p4 labels‘로 인쇄되지 않았는지 확인합니다 . POSIX 에 따르면
이것은 문제가 됩니다 .

파이프 라인 예약어로 시작하는 경우 ” !command1하부 쉘 명령이며, 애플리케이션이되도록한다 (시작에서 오퍼레이터 command1로부터 분리되어 !하나 개 이상의 <blank>캐릭터.
예약어의 동작은 !바로 다음에 (오퍼레이터가 지정한다.

대부분의 일반적인 셸은 여전히이 ‘ !‘를 “파이프 라인에서 마지막 명령의 종료 코드를 부정”하는 것으로 해석하지만 ‘ ‘ mksh/lksh대신 부정적인 파일 이름 패턴으로 해석하지 않습니다.
결과적으로 현재 디렉터리 ( ‘ main‘ 라는 단일 디렉터리 포함)의 경로 이름으로 구성된 명령을 실행하려고 시도합니다 . 물론 테스트에 실패합니다.

!‘와 ‘ (‘ 사이에 공백을 추가하여 간단히 수정할 수 있지만 대신 불필요한 하위 쉘을 제거하여 수정하겠습니다. 특히 커밋 74ec8cf


답변

!없이, 서브 쉘없이, if없이, 최소한 bash에서 작동해야합니다.

ls nonexistingpath; test $? -eq 2 && echo "yes, nonexistingpath doesn't exist."

# alternatively without error message and handling of any error code > 0
ls nonexistingpath 2>/dev/null; test $? -gt 0 && echo "yes, nonexistingpath doesn't exist."