[질문] redirection과 괄호의 사용에 대해서. cmd 3>&2 2>&1 1>&3- >outf 2>errf 와 (cmd 3>&2 2>&1 1>&3-) >outf 2>errf 의 차이는?

이종진의 이미지

shell script를 보던 중 >&라는 것을 보고 manpage을 통해 fd 복제의 기능을 한다는 것을 알게 되었습니다.
>&을 사용한 fd 복제와 ()에 의한 괄호안 내용 subshell실행을 test하기 위해서
아래와 같은 cmd라는 shell script file을 만들어 봤습니다.

#!/bin/sh
echo "stdout"
echo "stderr" >&2

즉 cmd는 stdout으로 "stdout"라는 문자를, stderr로 "stderr"라는 문자를 출력합니다.
그리고
3>&2 2>&1 1>&3-
는 결국 fd 1과 fd 2를 exchange하여 둘다 tty로 향하지만 1이 stderr가, 2가 stdout이 된다고 알고 있습니다.

만일 아래와 같이 명령을 내리면

cmd 3>&2 2>&1 1>&3- >outf 2>errf

outf에는 stdout
errf에는 stderr
라는 문자가 입력됩니다.
stdout, stderr에 상관없이 outf로는 fd1이 redirect되고 errf로는 fd2가 redirect되므로 당연한 현상이라고 생각합니다.

그러나 아래와 같이 괄호는 사용하면

(cmd 3>&2 2>&1 1>&3-) >outf 2>errf

outf에는 stderr
errf에는 stdout
라는 문자가 입력됩니다.

왜 이렇게 되는지 설명해 알려주시면 고맙겠습니다.

ymir의 이미지

shell 의 redirection 은 역순으로 진행된다고 이해하시면 편할 것 같습니다.

  cmd 3>&2 2>&1 1>&3- >outf 2>errf

위 명령은 일단 stdout 과 stderr 를 각각 outf 와 errf 로 보낸 후에, 1->3, 2->1, 3->2 의 순으로 redirection 이 이루어집니다.

정확히 본래의 의도대로 stderr 와 stdout 이 바뀌어서 저장되도록 만드시려면, 아래와 같이 순서를 바꾸셔야 합니다.

  cmd >outf 2>errf 3>&2 2>&1 1>&3

물론 본문에서 제시하신 두번째 명령과 같이, sub-shell 로 미리 처리를 해도 됩니다.

  (cmd 3>&2 2>&1 1>&3-) >outf 2>errf

(someting in sub-shell) 의 출력 중 stdout 과 stderr 를 각각 outf 와 errf 로 보냈는데, sub-shell 내에서 둘의 fd 를 바꾸었죠.

아래 bash ref. manual 의 redirections 항목을 살펴보세요.

http://www.gnu.org/software/bash/manual/bashref.html#Redirections

되면 한다! / feel no sorrow, feel no pain, feel no hurt, there's nothing gained.. only love will then remain.. 『 Mizz 』

되면 한다! / feel no sorrow, feel no pain, feel no hurt, there's nothing gained.. only love will then remain.. 『 Mizz 』