나는 두 가지 접근 방식을 모두 보았고 <<<'foo'
이를 <(echo 'foo')
에코 파이프( )의 대안으로 제안했습니다 echo foo | cat
.
cat과 함께 이 두 구조를 사용하면 다음과 같은 결과를 얻습니다.
$ cat <<<'foo'
foo
$ cat <(echo 'foo')
foo
지금까지도 그렇습니다.
그러나 셸에서 직접 사용하면 차이점이 분명해집니다.
$ <<<'foo'
foo
$ <(echo 'foo')
zsh: permission denied: /dev/fd/12
저는 zsh를 사용하고 있는데 bash는 <<<
이 경우를 다르게 처리하는 것 같습니다. 아무것도 인쇄하지 않고 이 경우 zsh와 같습니다 <()
.
하지만 실제로 내 질문을 제기하는 것은 한 가지 차이점입니다.
$ diff <<<"/mypath" <(pwd)
diff: missing operand after `/dev/fd/63'
diff: Try `diff --help' for more information.
이 두 가지 유형의 셸 리디렉션 간에는 근본적인 차이점이 있다는 것이 분명합니다. 누구든지 차이점을 설명할 수 있나요?
답변1
<<< text
명령의 파일 설명자에 영향을 미치는 경우 리디렉션입니다(여기서는 0이지만 4<<< text
fd 4에 영향을 줍니다).
while은 <(...)
리디렉션이 아닌 확장/대체입니다. 파일 이름으로 확장됩니다. 명령에 삽입되면 명령에 전달되는 매개변수에 영향을 줍니다.
cat <(echo test)
cat
인수와 유사한 파일을 사용하여 실행합니다 /dev/fd/12
. 그리고 fd 12는 파이프의 읽기 끝에서도 열려 있습니다. cat
fd 12에서는 읽지 않지만 파일을 열면 /dev/fd/12
fd 12와 동일한 파이프를 가리키는 새 fd(아마도 3)를 얻게 됩니다.
echo test
백그라운드에서 실행되는 동안 fd 1은 동일한 파이프의 쓰기 끝 부분에 연결되므로 echo
결국 cat
해당 파이프를 통해 연결됩니다(통신 채널은 설정하기가 그보다 더 복잡하지만 echo text | cat
).
cat <<< text
인수 없이 cat을 실행하고 fd 0을 열어 포함된 test\n
.
zsh 설명
<<< test
~처럼
$NULLCMD <<< test
이는 리디렉션만 포함된 항목을 실행할 때마다 ( $NULLCMD
일반적으로 ) 발생합니다( 리디렉션이 cat
하나만 있는 경우 (일반적으로 호출기)가 사용되지 않는 한).<
$READNULLCMD
존재하다:
<(echo text)
리디렉션은 없으며 단지 프로세스 대체가 있으며 /dev/fd/12 매개변수로 확장됩니다. 이것은 쉘에게 파일을 실행하도록 요청합니다.
zsh에서는 다음을 사용해도 실질적인 이점이 없습니다.
cat <(echo test)
cat < <(echo test)
초과하다
echo test | cat
Bash와 같은 다른 셸에서 이 구성을 볼 수 있습니다. 예를 들면 다음과 같습니다.
IFS= read -r var < <(echo text)
하지만 그 이유는 해당 쉘에서는 하위 프로세스에서 실행되기 echo text | IFS= read -r var
때문에 작동하지 않기 때문입니다 . read
그렇지 않다 zsh
.
프로세스 대체는 표준 입력이 아닌 파일 이름을 통한 입력만 인수로 허용하는 명령과 diff <(cmd1) <(cmd2)
.
와 zsh
사이의 한 가지 차이점 은 후자가 기다리지 않는다는 것입니다. 비록 두 가지 종료 상태를 모두 사용할 수 있게 만드는 경우에만 대기하고 들어갑니다. 와 비교됩니다.cmd1 | cmd2
cmd2 < <(cmd1)
zsh
cmd1
cmd1
cmd2
cmd1 | cmd2
$pipestatus
sleep 1 | uname
uname < <(sleep 1)
cmd <<< foo
cmd
입력을 찾아야 할 때 유용합니다( zsh
여기서 문서와 같은 문자열은 파이프가 아닌 임시 파일을 사용하여 구현되기 때문입니다).