Bash 블록 리디렉션 및 파이프

Bash 블록 리디렉션 및 파이프

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코드를 검사하는 데에도 사용할 수 있습니다 . 대부분의 오류를 더 빨리 찾는 데 도움이 됩니다.

관련 정보