표준 출력을 여러 명령으로 보내는 방법은 무엇입니까?

표준 출력을 여러 명령으로 보내는 방법은 무엇입니까?

입력을 필터링하거나 그에 따라 작동한 다음 이를 출력으로 전달하는 명령이 있습니다. 일반적으로 그런 경우라고 생각합니다 stdout. 그러나 입력을 받아들이고 stdin아무 작업도 수행하고 아무것도 출력하지 않는 명령도 있습니다.

저는 OS X에 가장 익숙하기 때문에 즉시 떠오르는 두 가지는 다음 pbcopy과 같습니다 pbpaste. - 시스템 클립보드에 액세스하는 방법은 다음과 같습니다.

어쨌든, stdout을 얻고 출력을 두 개의 파일로 내보내고 싶다면 stdout이 명령을 사용할 수 있다는 것을 알고 있습니다 tee. 나는 그것에 대해 뭔가를 알고 있지만 xargs그것이 내가 찾고 있는 것이 아니라고 생각합니다.

stdout두 개 이상의 명령 사이를 전환하기 위해 분할하는 방법을 알고 싶습니다 . 예를 들어:

cat file.txt | stdout-split -c1 pbcopy -c2 grep -i errors

아마도 그것보다 더 좋은 예가 있을 것입니다. 그러나 "음소거"를 피하면서 이를 중계하지 않는 명령에 stdout을 보내는 방법을 알고 싶습니다. 파일과 그 일부를 stdout보내는 방법을 묻는 것이 아닙니다. 및 클립보드에 복사 - 특정 명령은 그다지 중요하지 않습니다.catgrep

또한 - 파일로 보내는 방법을 묻는 것이 아닙니다 stdout. "중복" 질문일 수 있습니다(죄송합니다). 하지만 검색을 좀 해보니 stdout과 파일을 분할하는 방법을 묻는 비슷한 질문만 찾을 수 있었습니다. - 답변 이 질문에는 tee, 나는 그것이 나에게 효과가 없을 것이라고 생각합니다.

마지막으로 "파이프라인 체인의 마지막 항목으로 pbcopy를 만드는 것이 어떨까요?"라고 물을 수 있습니다. 내 대답은 1) 이를 사용하고 싶지만 콘솔에서 출력을 계속 보려면 어떻게 해야 합니까? 2) 입력을 처리한 후 출력되지 않는 두 개의 명령을 사용하고 싶다면 stdout어떻게 해야 하나요 ?

tee아, 한 가지 더 - 명명된 파이프( )를 사용할 수 있다는 것을 알고 있지만 mkfifo미리 설정할 필요 없이 이 작업을 인라인으로 간결하게 수행할 수 있는 방법이 있기를 바랐습니다. :)

답변1

대체 항목을 사용 tee하고 처리할 수 있습니다.

cat file.txt | tee >(pbcopy) | grep errors

이렇게 하면 모든 출력이 로 전송되며 cat file.txt콘솔에서만 pbcopy결과를 얻을 수 있습니다.grep

tee이 섹션에는 여러 프로세스를 배치 할 수 있습니다 .

cat file.txt | tee >(pbcopy) >(do_stuff) >(do_more_stuff) | grep errors

답변2

에 여러 파일 이름을 지정할 수 있으며 tee, 또한 표준 출력을 명령으로 파이프할 수 있습니다. 출력을 여러 명령으로 디스패치하려면 여러 파이프를 만들고 각 파이프를 출력으로 지정해야 합니다 tee. 이를 수행하는 방법에는 여러 가지가 있습니다.

프로세스 대체

쉘이 ksh93, bash 또는 zsh인 경우 프로세스 대체를 사용할 수 있습니다. 이는 파일 이름을 기대하는 명령에 파이프를 전달하는 방법입니다. 쉘은 파이프를 생성하고 /dev/fd/3명령처럼 파일 이름을 전달합니다. 번호는파일 설명자파이프가 연결되어 있습니다. 일부 UNIX 변형에서는 지원되지 않습니다 /dev/fd. 대신 명명된 파이프가 사용됩니다(아래 참조).

tee >(command1) >(command2) | command3

파일 설명자

모든 POSIX 셸에서 여러 가지를 사용할 수 있습니다.파일 설명자분명히. /dev/fd출력 중 하나를 제외한 모든 항목을 tee이름으로 지정해야 하므로 이를 위해서는 지원되는 unix 변형이 필요합니다 .

{ { { tee /dev/fd/3 /dev/fd/4 | command1 >&9;
    } 3>&1 | command2 >&9;
  } 4>&1 | command3 >&9;
} 9>&1

명명된 파이프

가장 기본적이고 이식 가능한 방법은 다음을 사용하는 것입니다.명명된 파이프. 단점은 쓰기 가능한 디렉터리를 찾아 파이프를 만든 다음 정리해야 한다는 것입니다.

tmp_dir=$(mktemp -d)
mkfifo "$tmp_dir/f1" "$tmp_dir/f2"
command1 <"$tmp_dir/f1" & pid1=$!
command2 <"$tmp_dir/f2" & pid2=$!
tee "$tmp_dir/f1" "$tmp_dir/f2" | command3
rm -rf "$tmp_dir"
wait $pid1 $pid2

답변3

프로세스 대체를 가지고 놀아보세요.

mycommand_exec |tee >(grep ook > ook.txt) >(grep eek > eek.txt)

grepmycommand_exec출력이 프로세스별 입력과 동일한 두 개의 바이너리입니다.

답변4

게다가pee~에서더 많은 유틸리티팩. 이는 다음을 위해 설계되었습니다:

pee 'command1' 'command2' 'cat -'

관련 정보