bash 리디렉션을 배우고 있습니다. 아래 코드가 ls | grep foo | grep bar
.
#!/bin/bash
{
{
ls | grep foo
} 2>&1 1>&4 | grep bar
} 4>&1
이는 foo와 일치하지만 foo 및 bar와는 일치하지 않습니다. 2>&1
나는 fd 1의 파이프가 fd 2에 복사된 다음 fd 1을 stdout으로 재설정하기 때문에 이것이 작동할 것이라고 생각합니다 .
중괄호(컨텍스트)를 유지하면서 이 코드를 수정할 수 있나요? 제거하면 2>&1 1>&4
예상대로 작동합니다. 그러나 나는 배우고 싶다.
파이프의 왼쪽에서는 stdout만 필요하다고 생각하므로 파이프를 fd 2에 복사하더라도 여전히 파이프의 왼쪽에서 fd 1만 찾습니다.
인용하다:https://wiki.bash-hackers.org/howto/redirection_tutorial#an_example
위에 참조된 링크에는 cmd1의 fd 2가 cmd3의 fd 0을 가리키는 다이어그램이 있습니다. 나는 나의 예를 통해 이것을 확인하려고 노력하고 있습니다.
답변1
당신의 시도:
{
{
ls | grep foo # goes to stdout (fd 1)
} 2>&1 1>&4 | grep bar # at this level: 2 now points to where fd1 is pointing (stdout), and 1 is *then* directed to the new fd 4 (ie to stdin of the outside curly)
} 4>&1 ## at this shell 'level', a new fd 4 is now pointing to where 1 is pointing: stdout
: 따라서 grep 막대는 { ls | grep foo }의 stderr에서만 수행되므로 빈 표준 입력에서는 { ls | grep foo }의 stderr이 { ls grep foo } grep foo로 이동합니다. }.파일 이름이 표시되지 않습니다. 이 파일 이름을 fd 4에 입력해 보세요:
{
{
ls | grep foo
} 2>&1 1>&4
} 4>&1 | grep bar
또는
{
{
ls | grep foo
} 2>&1 1>&4 | <&4 grep bar
} 4>&1
비교하고...
참고: 내부 명령의 stderr도 stdout으로 이동하려면 이를 두 번째 위치에 복사해야 합니다. 1>&4 2>&1 [즉: 1은 이제 fd 4로 이동하고 2는 1이 있는 위치로 이동합니다. 이제 가리키는 것, 즉 fd 4 및 ]
답변2
내가 아는 한 다음은 사실입니다.
이것
{
{
ls | grep foo
} 2>&1 1>&4 | grep bar
} 4>&1
동등하다
(ls | grep foo 2>&1 1>&4 | grep bar) 4>&1
fd 4가 /dev/pts/0이고 1>&4로 인해 fd 1이 파이프 대신 동일한 /dev/pts/0을 갖게 되므로 실패합니다.
답변3
리디렉션을 통해 데이터를 복사하려는 것 같나요? tee
당신이 배우는 동안 나는 더 이상 일을 망치지 않을 것입니다 .
shellcheck
코드를 검사하는 데에도 사용할 수 있습니다 . 대부분의 오류를 더 빨리 찾는 데 도움이 됩니다.