답변:
그들 사이의 차이점을 알아내는 좋은 방법은 커맨드 라인에서 약간의 실험을하는 것입니다. <
캐릭터 의 시각적 유사성에도 불구하고 리디렉션이나 파이프와는 매우 다른 일을합니다.
date
테스트를 위해 명령을 사용합시다 .
$ date | cat
Thu Jul 21 12:39:18 EEST 2011
이것은 무의미한 예이지만 STDIN cat
의 출력 을 수락하고 date
다시 뱉어내는 것을 보여줍니다 . 프로세스 대체를 통해 동일한 결과를 얻을 수 있습니다.
$ cat <(date)
Thu Jul 21 12:40:53 EEST 2011
그러나 막 뒤에서 일어난 일은 달랐습니다. STDIN 스트림을받는 대신 cat
실제로 열어서 읽어야하는 파일 이름이 전달되었습니다. echo
대신 이 단계를 사용하여 볼 수 있습니다 cat
.
$ echo <(date)
/proc/self/fd/11
cat이 파일 이름을 받으면 파일 내용을 읽습니다. 반면에 echo는 전달 된 파일 이름을 보여주었습니다. 대체를 더 추가하면이 차이가 더 분명해집니다.
$ cat <(date) <(date) <(date)
Thu Jul 21 12:44:45 EEST 2011
Thu Jul 21 12:44:45 EEST 2011
Thu Jul 21 12:44:45 EEST 2011
$ echo <(date) <(date) <(date)
/proc/self/fd/11 /proc/self/fd/12 /proc/self/fd/13
프로세스 대체 (파일 생성)와 입력 경로 재 지정 (파일을 STDIN에 연결)을 결합 할 수 있습니다.
$ cat < <(date)
Thu Jul 21 12:46:22 EEST 2011
거의 동일하게 보이지만 이번에는 cat이 파일 이름 대신 STDIN 스트림을 통과했습니다. echo로 시도하여 이것을 볼 수 있습니다.
$ echo < <(date)
<blank>
echo는 STDIN을 읽지 않고 인수가 전달되지 않았으므로 아무것도 얻지 못합니다.
파이프 및 입력 리디렉션은 컨텐츠를 STDIN 스트림으로 전달합니다. 프로세스 대체는 명령을 실행하고 출력을 특수 임시 파일에 저장 한 다음 명령 대신 해당 파일 이름을 전달합니다. 어떤 명령을 사용하든 파일 이름으로 취급합니다. 작성된 파일은 일반 파일이 아니라 더 이상 필요하지 않으면 자동으로 제거되는 명명 된 파이프입니다.
[[ -p <(date) ]] && echo true
. 이것은 true
bash 4.4 또는 3.2로 실행할 때 생성 됩니다.
bash
posix 쉘에는 프로세스 대체 가 없기 때문에 다른 고급 쉘 에 대해 이야기하고 있다고 가정해야합니다 .
bash
수동 페이지 보고서 :
프로세스 대체
프로세스 대체는 명명 된 파이프 (FIFO) 또는 / dev / fd 열린 파일 이름 지정 방법을 지원하는 시스템에서 지원됩니다. <(list) 또는> (list) 형식입니다. 프로세스 목록은 입력 또는 출력이 FIFO 또는 / dev / fd의 일부 파일에 연결된 상태로 실행됩니다. 이 파일의 이름은 확장 결과로 현재 명령에 인수로 전달됩니다. > (list) 양식을 사용하는 경우 파일에 쓰면 목록에 대한 입력이 제공됩니다. <(list) 형식을 사용하는 경우 인수로 전달 된 파일을 읽어 목록의 출력을 확보해야합니다.
사용 가능한 경우 프로세스 대체는 매개 변수 및 변수 확장, 명령 대체 및 산술 확장과 동시에 수행됩니다.
다시 말해 실제 관점에서 다음과 같은 표현식을 사용할 수 있습니다.
<(commands)
파일을 매개 변수로 요구하는 다른 명령의 파일 이름으로. 또는 이러한 파일에 대한 리디렉션을 사용할 수 있습니다.
while read line; do something; done < <(commands)
귀하의 질문으로 돌아가서, 프로세스 대체와 파이프는별로 공통적이지 않은 것 같습니다.
여러 명령의 출력을 순서대로 파이프하려면 다음 형식 중 하나를 사용할 수 있습니다.
(command1; command2) | command3
{ command1; command2; } | command3
프로세스 대체에 리디렉션을 사용할 수도 있습니다.
command3 < <(command1; command2)
마지막으로 command3
파일 매개 변수를 수락하면 (stdin 대신)
command3 <(command1; command2)
그렇지 않으면 불가능한 프로세스 대체로 수행 할 수있는 세 가지 작업이 있습니다.
diff <(cd /foo/bar/; ls) <(cd /foo/baz; ls)
파이프로는 이것을 할 수있는 방법이 없습니다.
다음이 있다고 가정하십시오.
curl -o - http://example.com/script.sh
#/bin/bash
read LINE
echo "You said ${LINE}!"
그리고 당신은 그것을 직접 실행하고 싶습니다. 다음은 비참하게 실패합니다. Bash는 이미 STDIN을 사용하여 스크립트를 읽으므로 다른 입력은 불가능합니다.
curl -o - http://example.com/script.sh | bash
그러나이 방법은 완벽하게 작동합니다.
bash <(curl -o - http://example.com/script.sh)
또한 프로세스 대체는 다른 방식으로도 작동합니다. 따라서 다음과 같이 할 수 있습니다.
(ls /proc/*/exe >/dev/null) 2> >(sed -n \
'/Permission denied/ s/.*\(\/proc.*\):.*/\1/p' > denied.txt )
이 예제는 약간 복잡하지만 stdout 을으로 보내고 stderr 을 sed 스크립트로 /dev/null
파이프 하여 "Permission denied"오류가 표시된 파일의 이름을 추출한 다음 THOSE 결과를 파일로 보냅니다.
첫 번째 명령과 stdout 리디렉션은 괄호 ( subshell )로되어 있으므로 THAT 명령의 결과 만 전송되고 /dev/null
나머지 행은 엉망이되지 않습니다.
diff
예에서는 cd
실패한 경우에 대해 관심을 가질 수 있습니다 diff <(cd /foo/bar/ && ls) <(cd /foo/baz && ls)
.
명령이 파일 목록을 인수로 사용하여 해당 파일을 입력 (또는 출력은 아니지만 일반적으로 출력)으로 처리하는 경우 해당 파일 각각은 프로세스 대체에 의해 투명하게 제공되는 명명 된 파이프 또는 / dev / fd 의사 파일 일 수 있습니다.
$ sort -m <(command1) <(command2) <(command3)
sort는 명령 줄에서 입력 파일 목록을 가져올 수 있으므로 정렬 할 세 명령의 출력을 "파이프"합니다.
<()
는 많은 고급 쉘 기능과 마찬가지로 원래 ksh 기능이며 bash 및 zsh에 의해 채택되었습니다. psub
POSIX와 관련이없는 물고기 기능입니다.
프로세스 대체는 형식으로 제한되지 않으며 파일 <(command)
의 출력을 사용 command
합니다. >(command)
파일을 입력으로 공급하는 형식 일 수도 있습니다 command
. 이것은 @enzotib의 답변에서 bash 매뉴얼을 인용 할 때도 언급됩니다.
date | cat
위 의 예에서 양식의 프로세스 대체를 사용 >(command)
하여 동일한 효과를 달성 하는 명령은 다음과 같습니다.
date > >(cat)
점을 유의 >
전에이 >(cat)
필요하다. 이것은 echo
@Caleb의 답변에서와 같이 다시 명확하게 설명 될 수 있습니다 .
$ echo >(cat)
/dev/fd/63
그래서, 추가하지 않고 >
, date >(cat)
같은 것 date /dev/fd/63
stderr에 메시지를 인쇄 할 수있다.
당신은 단지 매개 변수로 파일 이름을 소요하고 처리하지 않는 프로그램이 가정 stdin
또는 stdout
. 지나치게 단순화 된 스크립트 psub.sh
를 사용하여 이를 설명하겠습니다. 의 내용 psub.sh
은
#!/bin/bash
[ -e "$1" -a -e "$2" ] && awk '{print $1}' "$1" > "$2"
기본적으로 두 인수가 모두 파일인지 (일반 파일 일 필요는 없음) 테스트하며,이 경우 awk "$1"
를 "$2"
사용하여 각 행의 첫 번째 필드를 작성하십시오 . 그리고 지금까지 언급 한 모든 것을 결합한 명령은
./psub.sh <(printf "a a\nc c\nb b") >(sort)
이것은 인쇄됩니다
a
b
c
그리고
printf "a a\nc c\nb b" | awk '{print $1}' | sort
그러나 다음은 작동하지 않으며 여기에서 프로세스 대체를 사용해야합니다.
printf "a a\nc c\nb b" | ./psub.sh | sort
또는 동등한 형태
printf "a a\nc c\nb b" | ./psub.sh /dev/stdin /dev/stdout | sort
위에서 언급 한 것 외에 ./psub.sh
읽은 경우 stdin
에는 이와 동등한 형식이 존재하지 않으며,이 경우 프로세스 대체 대신 사용할 수있는 것이 없습니다 (물론 명명 된 파이프 또는 임시 파일을 사용할 수도 있지만 이는 또 다른 것입니다) 이야기).