파일 설명자를 더 잘 이해하기 위해 사용하려고 하는데 다음 내용을 이해할 수 없습니다.
$ grep "..." 3>&1 1>/dev/null
1
12
13
123
321
3
위의 내용은 셸에서 일치하는 항목을 표시하지 않습니다. 이는 /dev/null로 리디렉션하기 때문에 분명히 발생합니다. 내가 이해하지 못하는 것은 3>&1
fd 3에 복사한 이후로 출력을 계속 볼 수 있도록 이렇게 하면 안되는 이유입니다.
내가 무엇을 놓치고 있나요?
답변1
귀하의 리디렉션하다FD 3을 FD 1의 복사본으로 만들어 FD 3이 stdout 등을 가리킬 것입니다.그것에 쓰다(기본적으로) TTY로 이동합니다. 그러면 FD 1이 로 리디렉션되므로 /dev/null
FD 1에 기록된 모든 내용은 삭제됩니다. grep
FD 3은 기록되지 않으므로 눈에 보이는 어떤 일도 발생하지 않습니다 .
순서대로 발생합니다. 먼저 복사본(dup2
)는 FD 3을 가리키므로 FD 3은 이제부터 FD 1이 현재 가리키는 것을 가리키고 FD 1은 를 가리키는 포인터로 대체됩니다 /dev/null
.
최종 결과는 그림에 나와 있습니다.아래 그림과 같이:
표준 오류(분홍색, FD 2) 및 FD 3은 TTY로 전송되고 표준 출력은 로 전송됩니다 /dev/null
. FD 3은 복사할 때 FD 1이 가리키는 곳이기 때문에 여전히 TTY를 가리킵니다. 그러나 이 grep
명령은 FD 3에 아무 것도 쓰려고 시도하지 않으므로 복사본은 전혀 사용되지 않습니다.
"복사"는 방향성입니다. 3>&1
처리 후 FD 3에 기록된 모든 내용은 처리 시 FD 1이 가리키는 위치로 이동합니다. 그 이상은 "보존"하지 않습니다. 그런 다음 FD 1을 리디렉션하면 여기에 기록된 모든 내용이 새 위치로 이동됩니다. 수행하는 작업은 나중에 사용하려는 경우를 대비하여 FD 1의 원래 대상에 유지됩니다. grep
표준 출력의 최종 위치에 영향을 미치는 유일한 리디렉션은 1>...
어디로 가는지 명시적으로 알려주는 리디렉션입니다.
만약에grep
예FD 3을 작성하면 예상대로 터미널에 나타납니다. 일반적으로 FD 1로만 출력하므로 실제 출력은 모두 폐기됩니다.
원하는 경우 FD 3에 grep 출력을 만들 수 있습니다.
( grep "..." >&3 )
이는 FD 1의 일반 출력을 가져와 (새로 생성된) FD 3을 가리킵니다. 직접 실행하면 FD 3가 아무데도 가지 않기 때문에 작동하지 않지만 다음과 같이 병합하여 활용할 수 있습니다.
( grep "..." >&3 ) 3>&1 1>/dev/null
괄호 안의 명령은 FD3으로 출력됩니다. 후속 리디렉션은 1) FD 3(현재 실제로 콘텐츠가 있음)을 FD 1로 지정한 다음, 2) FD 1을 다시 지정합니다(이는 효과가 없습니다). 최종 결과는 grep "..."
어떤 소란도 없이 정확히 있어야 할 위치에서 다시 표준 출력으로 출력을 얻을 수 있다는 것입니다.
이 리디렉션이 실제로 수행하는 작업은 다음과 같습니다.그것은 마치
cmd 3>&1 1>&2 2>&3 3>&- | foo
FD 3을 임시 저장 지점으로 사용하여 FD 1과 2를 교환합니다. 때로는 쉘 스크립팅 트릭에도 사용됩니다.POSIX sh에서 가짜 프로세스 교체( cmd1 | ( cmd2 | ( main_command /dev/fd/3 /dev/fd/4 ) 4<&0 ) 3<&0 )
. 그렇지 않으면 명령 자체가 비표준 파일 설명자를 숫자로 사용하는 경우는 거의 없습니다(물론 많은 명령이 파일 자체를 열고 가져옵니다).
답변2
파일 설명자를 리디렉션하고 있습니다.삼파일 설명자에1, 1을 /dev/null로 리디렉션합니다. 당신은 아무것도 복사하지 않았습니다.
일반적인 방법은복사파일 설명자에는 tee
.
또한 귀하의 컨텍스트가 무엇인지 모르지만 3은 내장 파일 설명자가 아닙니다. 아마도 뭔가를 가리키도록 설정했을 것입니다.