편집 : 탈선하여 요청한 질문과 다른 질문에 답하게 된 것을 봅니다. 실제 질문에 대한 답변은 Paul Tomblin의 답변 하단에 있습니다. (어떤 이유로 stdout과 stderr를 별도로 리디렉션하도록 해당 솔루션을 향상 시키려면 여기에서 설명하는 기술을 사용할 수 있습니다.)
나는 stdout과 stderr의 구별을 유지하는 답변을 원했습니다. 불행히도 지금까지 그 구별을 유지하는 모든 답변은 인종에 취약합니다. 제가 코멘트에서 지적했듯이 프로그램이 불완전한 입력을 보는 위험이 있습니다.
나는 마침내 구별을 유지하고 인종에 취약하지 않고 끔찍하게 어리석지 않은 답을 찾았다 고 생각합니다.
첫 번째 빌딩 블록 : stdout과 stderr를 바꾸려면 :
my_command 3>&1 1>&2 2>&3-
두 번째 빌딩 블록 : stderr 만 필터링 (예 : 티)하려면 stdout & stderr를 교체하고 필터링 한 다음 다시 교체하여이를 수행 할 수 있습니다.
{ my_command 3>&1 1>&2 2>&3- | stderr_filter;} 3>&1 1>&2 2>&3-
이제 나머지는 간단합니다. 처음에 stdout 필터를 추가 할 수 있습니다.
{ { my_command | stdout_filter;} 3>&1 1>&2 2>&3- | stderr_filter;} 3>&1 1>&2 2>&3-
또는 끝에 :
{ my_command 3>&1 1>&2 2>&3- | stderr_filter;} 3>&1 1>&2 2>&3- | stdout_filter
위의 두 명령이 모두 작동한다는 것을 확신하기 위해 다음을 사용했습니다.
alias my_command='{ echo "to stdout"; echo "to stderr" >&2;}'
alias stdout_filter='{ sleep 1; sed -u "s/^/teed stdout: /" | tee stdout.txt;}'
alias stderr_filter='{ sleep 2; sed -u "s/^/teed stderr: /" | tee stderr.txt;}'
출력은 다음과 같습니다.
...(1 second pause)...
teed stdout: to stdout
...(another 1 second pause)...
teed stderr: to stderr
내 프롬프트는 teed stderr: to stderr
예상대로 " " 바로 뒤에 다시 표시 됩니다.
zsh에 대한 각주 :
위의 솔루션은 bash에서 작동하지만 (확실하지 않은 다른 셸도있을 수 있음) zsh에서는 작동하지 않습니다. zsh에서 실패하는 이유는 두 가지입니다.
- 구문
2>&3-
은 zsh에서 이해되지 않습니다. 다시 작성해야합니다.2>&3 3>&-
- zsh에서 (다른 셸과 달리) 이미 열려있는 파일 설명자를 리디렉션하면 경우에 따라 (결정 방법을 완전히 이해하지 못함) 대신 내장 티와 같은 동작을 수행합니다. 이를 방지하려면 리디렉션하기 전에 각 fd를 닫아야합니다.
예를 들어 두 번째 솔루션은 zsh에 대해 {my_command 3>&1 1>&- 1>&2 2>&- 2>&3 3>&- | stderr_filter;} 3>&1 1>&- 1>&2 2>&- 2>&3 3>&- | stdout_filter
(bash에서도 작동하지만 매우 장황합니다) 로 다시 작성해야합니다 .
반면에 zsh의 신비한 내장 암시 적 티잉을 활용하여 티를 전혀 실행하지 않는 zsh에 대한 훨씬 더 짧은 솔루션을 얻을 수 있습니다.
my_command >&1 >stdout.txt 2>&2 2>stderr.txt
(필자는 문서에서 짐작하지 않았을 나는 것을 발견 >&1
하고 2>&2
트리거 zsh을의 암시 티잉하는 것입니다,. 내가 시행 착오에 의한 것을 발견)