쉘이 이러한 리디렉션을 다음과 같이 해석하는 이유는 무엇입니까?

쉘이 이러한 리디렉션을 다음과 같이 해석하는 이유는 무엇입니까?

쉘이 리디렉션을 구문 분석하는 방식에 대한 이상해 보이는 동작을 이해하도록 도와줄 수 있는 사람이 있습니까?

$ cat > test.txt
Line 1
Line 2
$ ls -i dummy.txt dummy2.txt
ls: dummy.txt: No such file or directory
ls: dummy2.txt: No such file or directory
$ 
$ cat test.txt > dummy.txt > dummy2.txt
$ cat dummy2.txt
Line 1
Line 2
$ cat dummy.txt
$

흥미로운! 나는 출력이 cat test.txt으로 리디렉션된 dummy.txt다음 쉘이 dummy.txt입력을 dummy2.txt. 그러나 어떻게 든 쉘은 그것을 다르게 구문 분석합니다 ...

test.txt그렇다면 에 대한 입력 으로 dummy2.txt의 내용을 어떻게 완전히 우회할 수 있습니까 dummy.txt?


노트: bash와 ksh에서 동일한 결과..

답변1

쉘이 리디렉션되지 않는다는 것을 아는 것이 중요합니다산출,하지만파일 설명자. POSIX 호환 운영 체제의 모든 프로세스에는 STDIN, STDOUT 및 STDERR의 세 가지 I/O 스트림이 있습니다. 리디렉션은 >STDOUT 스트림의 파일 설명자를 리디렉션합니다. 따라서 이 행을 구문 분석할 때 쉘이 보는 내용은 다음과 같습니다.

  1. cat test.txt- 좋아요, 프로그램을 실행 cat하고 매개변수를 입력하겠습니다.test.txt
  2. > dummy.txt- 아, 이제 프로세스의 STDOUT 설명자를 가져와서 cat"dummy.txt"라는 파일에 연결하겠습니다. 이전에 아무것도 없었는지 상관하지 않고 파일을 만들고 0으로 자르겠습니다.
  3. > dummy2.txt- 아, 이제 프로세스의 STDOUT 설명자 cat(이전에 "dummy.txt"에 연결한)를 가져와서 다른 새 파일에 연결하겠습니다. 대신 리디렉션하고 있기 때문에 동시에 두 가지를 모두 수행할 수 없습니다.반복하다파일 설명자.

그렇기 때문에 이 명령은 다음과 같습니다.

find / 2>&1 >/dev/null

STDOUT에서는 오류 출력이 발생하고 일반(STDOUT) 출력은 발생하지 않지만 다음과 같습니다.

find / >/dev/null 2>&1

결과는 전혀 출력되지 않습니다. 첫 번째 경우에는 STDERR을 STDOUT의 복사본(dup)에 넣은 다음 이전 STDOUT을 휴지통에 넣습니다. 두 번째에서는 먼저 STDOUT을 휴지통에 넣은 다음 이를 복사하고(여전히 를 가리키고 있음 /dev/null) STDERR도 거기에 넣습니다.

답변2

댓글부터 답변까지(그 중 일부는 추측임에도 불구하고):

Bash에서 실행 중인 경우,

cat test.txt > d1 > d2 > d3 > d4 > d5 

그러면 d1~d4는 비어 있고 test.txt의 내용은 d5에 저장됩니다. Bash는 지정된 마지막 파일에서만 실제 리디렉션을 수행하는 것 같습니다.

이상하게도 zsh(최소 버전 5)는 test.txt의 내용도 모든 중간 파일에 복사합니다.

Bash 매뉴얼 페이지에는 리디렉션 순서가 중요하다고 나와 있으므로 표시된 마지막 방향이 중개자보다 우선하는 것 같습니다. 그러나 파일이 거기에 있기 때문에 bash는 실제 콘텐츠가 어디로 가는지 알아내기 전에 파일을 생성합니다.

매뉴얼 페이지의 특정 부분은 다음과 같습니다.

Note that the order of redirections is significant.  For example, the command

              ls > dirlist 2>&1

directs both standard output and standard error to the file dirlist, 
while the command

              ls 2>&1 > dirlist

directs  only the standard output to file dirlist, because the standard 
error was duplicated from the standard output before the standard output
was redirected to dirlist.

이는 현재 상황을 구체적으로 다루지는 않지만 명령이 중요하다는 점을 시사합니다. 따라서 이상한 일(표준 출력을 다른 위치로 반복적으로 리디렉션)을 수행할 때 이상한 동작을 보면 놀라운 결과가 나올 수 있습니다.

나는 누군가가 이 추측에 있는 미친 (또는 사소한) 실수를 곧 바로잡을 것이라고 확신합니다 :-)

관련 정보