&&와 |의 차이점은 무엇입니까? bash 스크립트에서?


13

아래의 두 줄을 살펴보면 두 가지 다른 결과가 나타납니다.

p=$(cd ~ && pwd) ; echo $p
p=$(cd ~ |  pwd) ; echo $p

둘은 어떻게 다릅니 까?


@heemayl 감사합니다. 내 사건의 차이점을 추출해 주시겠습니까? 감사.
Nam G VU

1
힌트 : 양쪽의 명령 |이 서브 쉘에서 실행됩니다.
heemayl

답변:


21

에서 p=$(cd ~ && pwd):

  • 대체 명령 $()은 서브 쉘에서 실행됩니다.

  • cd ~디렉토리를 ~(집)으로 변경하고 , cd성공하면 ( &&) pwdSTDOUT에 디렉토리 이름 을 인쇄하므로 저장된 문자열 p은 홈 디렉토리가됩니다./home/foobar

에서 p=$(cd ~ | pwd):

  • 다시 $()서브 쉘을 생성합니다

  • |각 서브 쉘에서 실행되는 양쪽의 명령 (그리고 둘 다 동시에 시작 함)

  • 그래서 cd ~서브 쉘에서 수행하고, pwdA의 별도의 서브 쉘

  • 그래서 당신은 pwd명령을 실행하는 곳 에서 STDOUT 만 얻을 것입니다 . 이것은 상상할 수 있듯이 모든 디렉토리 일 수 있습니다. 따라서 p홈 디렉토리가 아닌 명령이 호출 된 곳의 디렉토리 이름을 포함합니다


명령 사이의 파이프의 목적은 무엇입니까? cd ~출력을 생성 pwd하지 않으며 입력을 읽지 않습니다.
Barmar

두 번째 명령은 본질적으로 (cd ~);p=$(pwd)그렇지 않습니까?
Barmar

@Barmar 예, OP가 사용한 것입니다. 설명해 드리고 있습니다.
heemayl

7

핵심 문제는 운영자 어떻게 &&하고 |두 개의 명령을 연결합니다.

&&종료 코드를 통해 명령을 연결합니다. 은 |파일 설명자 (표준 입력, 표준 출력)를 통해 두 명령을 연결합니다.

먼저 단순화하자. 과제를 제거하고 다음과 같이 쓸 수 있습니다.

echo $(cd ~ && pwd)
echo $(cd ~ | pwd)

명령 실행 서브 쉘을 제거하여이를 분석 할 수도 있습니다.

$ cd ~ && pwd
$ cd ~ | pwd

&&

명령이 실행되는 디렉토리를 표시하도록 프롬프트를 변경하면 다음과 같이 PS1='\w\$ '표시됩니다.

/tmp/user$ cd ~ && pwd
/home/user
~$ 
  • 명령 cd ~이 "현재 디렉토리"를 명령을 실행중인 실제 사용자의 홈으로 변경했습니다 ( /home/user).
  • 명령 결과 (종료 코드 0)가 성공하면 && 다음에 나오는 다음 명령이 실행됩니다.
  • 그리고 "현재 작업 디렉토리"가 인쇄됩니다.
  • 실행중인 쉘은 변경된 pwd~의 프롬프트가 표시 될 때 ~$.

어떤 이유로 디렉토리가 변경되지 않은 경우 (종료 코드가 0이 아님) (디렉토리가 존재하지 않고 권한이 디렉토리 읽기를 차단 함) 다음 명령이 실행되지 않습니다.

예:

/tmp/user$ false && pwd
/tmp/user$ _ 

종료 코드 1부터는 false다음 명령이 실행되지 않습니다.

따라서 "명령 1"의 종료 코드는 "명령 2"에 영향을줍니다.

이제 전체 명령의 효과 :

/tmp/user$ echo $(cd ~ && pwd)
/home/user
/tmp/user$ _

디렉토리가 변경되었지만 하위 쉘 내부 $(…)에서 변경된 디렉토리가 인쇄 /home/user되지만 하위 쉘이 닫히면 즉시 삭제됩니다. pwd는 초기 디렉토리 ( /tmp/user)로 돌아갑니다 .

|

이것이 일어나는 일입니다.

/tmp/user$ cd ~ | pwd
/tmp/user
/tmp/user$ _

메타 문자 |(실제 연산자가 아님)는 파이프의 각 측면에있는 각 명령 ( |)이 각각의 하위 쉘 내부에 설정되어 있는 "파이프"(bash)를 생성하도록 쉘에 신호를 보냅니다. 그런 다음 왼쪽 명령. /dev/stdin오른쪽 명령 의 입력 파일 디스크립터 ( )는 출력 디스크립터 ( /dev/stdout)에 연결되고 두 명령이 시작되어 상호 작용합니다. 왼쪽 명령 ( cd -)에는 출력이없고 오른쪽 명령 ( pwd)에는 입력이 없습니다. 따라서 각각은 자체 하위 쉘 내부에서 독립적으로 실행됩니다.

  • cd ~하나의 쉘의 비밀번호가 변경됩니다.
  • pwd다른 서브 - 쉘의 (완전 독립) PWD를 출력한다.

파이프가 끝날 때 각 쉘의 변경 사항은 무시되고 외부 서브 쉘은 pwd를 변경하지 않습니다.

이것이 두 명령이 "파일 디스크립터"에 의해서만 연결되는 이유입니다.
이 경우에는 아무것도 보내지 않으며 읽지 않습니다.

전체 명령 :

$ echo "$(cd ~ | pwd)"

명령이 실행 된 디렉토리 만 인쇄합니다.


5

당신이 '|'을 의미하는지 잘 모르겠습니다 또는 '||' 두 번째 경우.

'|' 쉘 파이프에서 한 명령의 출력을 다른 명령의 입력으로 파이프합니다. 일반적인 사용 사례는 다음과 같습니다. curl http://abcd.com/efgh | grep ijkl 즉 명령을 실행하고 다른 명령을 사용하여 명령의 출력을 처리합니다.

예를 들어, 'cd'는 일반적으로 출력을 생성하지 않으며 'pwd'는 입력을 기대하지 않으므로 무의미합니다.

'&&'및 '||' 그래도 파트너 명령입니다. 이들은 대부분의 언어에서 논리 "and"및 "or"연산자와 같은 방식으로 사용되도록 설계되었습니다. 그러나 수행되는 최적화는 쉘 프로그래밍 패러다임 인 특정 동작을 제공합니다.

논리적 "and"연산의 결과를 확인하려면 첫 번째 조건이 성공한 경우 두 번째 조건 만 평가하면됩니다. 첫 번째 조건이 실패하면 전체 결과는 항상 거짓입니다.

논리적 "또는"연산의 결과를 확인하려면 첫 번째 조건이 실패한 경우 두 번째 조건 만 평가하면됩니다. 첫 번째 조건이 성공하면 전체 결과는 항상 참입니다.

따라서 셸에서 완료된 command1 && command2 command2경우에만 실행되고 command1성공적인 결과 코드를 반환 한 경우입니다. 당신이 경우 command1 || command2 command2때 실행됩니다 command1완료되면 command1반환 오류 코드입니다.

또 다른 일반적인 패러다임은 command1테스트 명령이어야한다는 것입니다. 예를 들어 다음과 같이 한 줄 if / then 문을 생성합니다.

[ "$VAR" = "" ] && VAR="Value if empty"

변수가 현재 비어있는 경우 값을 변수에 할당하는 (긴 감기) 방법입니다.

Stack Exchange의 다른 곳에서이 프로세스를 사용하는 많은 예가 있습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.