대시의 파이프 및 리디렉션 이해

대시의 파이프 및 리디렉션 이해

누군가 두 명령의 출력을 파일로 다른 명령에 전달하는 방법을 물었고 그들은 다음과 같은 결과를 얻었습니다.답변다음과 같은.

( cmd1 | ( cmd2 | ( main_command /dev/fd/3 /dev/fd/4 ) 4<&0 ) 3<&0 )

이걸 분해해야 해요.

some_file에 입력으로 전달하려는 텍스트 파일이 있다고 가정해 보겠습니다 main_command. main_command두 개의 파일을 입력으로 사용합니다. 명령의 출력 main_command과 함께 사용 하려면 한 가지 방법은 다음과 같습니다.some_filecmd2

( cmd2 | ( main_command some_file /dev/fd/4 ) 4<&0 )
  • 그것의 "가장 깊은" 부분(즉, 모든 것이 최고점에 도달하는 부분)은 입니다 main_command some_file /dev/fd/4. 이것은 단지 파일 some_file/dev/fd/4를 인수로 전달합니다 main_command.
  • 4<&0부분은 stdin를 가리킬 파일 설명자를 나타냅니다 4.
  • cmd2 |의 출력을 후속 입력과 cmd2연결합니다 .
  • 괄호는 무슨 뜻인지 잘 모르겠습니다. 분석 목적으로만 존재합니까, 아니면 다른 목적으로 사용됩니까?

내 질문은 다음과 같습니다

  1. 질문 시작 부분에 있는 명령의 압축을 어떻게 풀 수 있나요?
  2. 괄호는 무엇을 하는가?
  3. 더 간단한 명령에 대한 설명이 맞습니까?

편집: 내 논리가 맞다면 1번 대답은 필요하지 않다고 말해야겠습니다.

답변1

이것은 상당히 복잡한 명령입니다. 마지막에 귀하의 질문에 직접 답변하지만 그 전에는 unzip 명령 자체에 관한 것입니다. 가능한 한 포괄적으로 설명하려고 노력했기 때문에 일부 장소에서는 필요한 것보다 더 자세할 수도 있습니다.

이것괄호는 서브쉘을 생성합니다:

( x y z )

새 셸이 현재 셸에서 생성되어 x y z실행됨(그런 다음 현재 셸로 반환됨)을 나타냅니다. 하위 쉘은 현재 쉘의 모든 것을 상속하지만 별도의 프로세스입니다. 즉, 상위 쉘에 영향을 주지 않고 내부적으로 입력을 파이프하고 자체 환경을 변경할 수 있습니다.

열려 있는 모든 파일에는 숫자로 된 "파일 설명자"가 있습니다.와 연관되다. 이 문서의 "파일"에는 실제 파일, 소켓 및 표준 I/O 스트림을 포함한 모든 유형의 입력 또는 출력 스트림이 포함됩니다. 이 숫자는 다음과 직접 비교할 수 있습니다.C read함수말하는 스트림을 식별하고 해당 시스템 호출과 운영 체제에서 제공하는 기타 모든 IO 기능을 사용합니다.

4<&0 리디렉션 수행표준 입력 파일 설명자(0)를 파일 설명자 4로 복제합니다.. 이것은 의미한다FD 0이 4에 복사되었습니다., 그 반대가 아니라. 이 경우 리디렉션 전에 하위 쉘의 열린 파일을 수정합니다. 현재 이것은 입력 스트림에 대한 또 다른 "이름"을 생성합니다. 그러나 중요한 부분은 이후 두 이름이 서로 독립적이라는 것입니다. FD 0이 다른 것을 참조하도록 변경되고 두 이름이 다른 경우에도 FD 4는 항상 동일한 스트림을 참조합니다.

/dev/fd/4프로그램이 자신이 연 파일 설명자에 액세스하는 (비표준) 방법입니다.. Linux에서는 /proc/self/fd현재 프로세스의 파일 설명자 테이블을 구체화하는 심볼릭 링크입니다 . 프로그램은 open("/dev/fd/4", O_RDONLY)프로그램이 FD 4에서 소유한 스트림(예: 4자체)을 참조하는 파일 핸들을 얻을 수 있습니다. 프로그램에 관한 한 이것은 다른 파일처럼 열고 닫고 읽을 수 있는 일반 파일일 뿐입니다. 열린 파일 설명자는 자식 프로세스에 의해 상속되기 때문에 main_command하위 프로세스에 있는 파일 설명자 4와 동일한 파일 설명자 4를 가지므로 /dev/fd/4그곳에서도 작동합니다.

cmd2 | xcmd2표준 출력을 실행 하고 표준 입력(또는 fd 0)에 연결합니다 x. 명령에는 x하위 쉘 표현식이 있습니다.


우리의 전반적인 명령

cmd2 | ( main_command /dev/fd/4 ) 4<&0

그런 다음 세 가지 주요 부분이 있습니다.

  1. 실행 cmd2하고 출력을 ( main_command /dev/fd/4 ) 4<&0.
  2. 의 (표준 입력)로 4식별된 스트림에 대해 다른 이름을 지정하십시오 .0( main_command /dev/fd/4 )
  3. main_command인수로 실행하면 /dev/fd/4(아마도) 파일로 열리고 읽혀서 cmd2.

최종 효과는 Bash 프로세스 대체와 정확히 동일하게 main_command의 출력에서 ​​열고 읽을 수 있는 경로 이름 인수를 얻는 것 입니다 . 실제로 이것은 인수로 제공될 수 있으며 그렇지 않은 경우 내부 처리는 매우 유사합니다.cmd2main_command <(cmd2)/dev/fd/63


완전한 명령의 경우

( cmd1 | ( cmd2 | ( main_command /dev/fd/3 /dev/fd/4 ) 4<&0 ) 3<&0 )

우리는 중첩된 하위 쉘을 가지고 있습니다. 이는 표준 입력의 복사본 두 개를 만들고 싶기 때문입니다.두 가지 다른 표준 입력: 하나는 더 큰 서브쉘로 파이프된 후 FD 3에 들어가는 의 출력이고 cmd1, 다른 하나는 cmd2가장 안쪽 서브쉘로 파이프된 후 FD 4에 들어가는 의 출력입니다. 두 0명령 모두 표준 입력을 참조하지만 서로 다른 입력을 파이프했기 때문에 각 명령의 표준 입력이 다릅니다.

나는 이것이 이 질문에서 가장 혼란스러운 부분이라고 생각합니다. 모든 명령(여기서 모든 서브쉘)에는그것은cmd1또는 에서 파이프된 표준 입력 cmd2과 해당 고유 표준 입력 스트림은 3또는 에 별칭이 지정됩니다 4. 이러한 열린 파일 설명자는 다음 수준의 하위 쉘 및 하위 명령에 의해 상속되므로, /dev/fd/3표준 입력이 이제 다른 것을 가리키더라도 가장 안쪽 명령은 외부에서 수행하는 것과 동일한 작업을 참조합니다.

외부 괄호는 일부 명령에 대해 약간 더 강력하고 좋은 습관이 될 수 있지만 반드시 필요한 것은 아닙니다. 내부적으로: 자체적인 리디렉션 세트를 가질 수 있을 뿐만 아니라 자체 표준 입력 스트림을 파이프할 수 있는 새로운 하위 프로세스를 생성하는 데 사용됩니다.

가장 안쪽 리디렉션은 실제로 중복됩니다. cmd2 | main_command /dev/fd/3 /dev/stdin표준 입력이 더 이상 변경되지 않기 때문에 작동합니다.


문제를 직접 해결하려면:

  1. 질문 시작 부분에 있는 명령의 압축을 어떻게 풀 수 있나요?

    지금까지의 포스팅은 언팩이 전부입니다.

  2. 괄호는 무엇을 하는가?

    대괄호는 입력 파이핑을 포함하여 다른 명령처럼 사용할 수 있지만 내부적으로 리디렉션과 같은 일반적인 셸 작업을 수행할 수 있는 별도의 셸 프로세스인 하위 셸을 생성합니다.

  3. 더 간단한 명령에 대한 설명이 맞습니까?

    부분적으로. 4<&0파일 설명자 4가 stdin을 가리킬 것이라고 가정하면 중요한 것은이제 stdin이라고 함- 표준입력의 개념이 아닙니다. /dev/fd/4"모든 것이 파일 의미입니다"에서 "파일"이지만 더 구체적으로 말하면 열 때 FD 4로 돌아가는 경로 이름입니다.

관련 정보