답변:
파이프는 다른 프로그램이나 유틸리티로 출력을 전달하는 데 사용됩니다 .
리디렉션은 출력을 파일이나 스트림 으로 전달하는 데 사용됩니다 .
예 : thing1 > thing2
vsthing1 | thing2
thing1 > thing2
thing1
thing1
출력되는 모든 파일은이라는 파일에 배치됩니다 thing2
. (참고- thing2
존재하는 경우 덮어 씁니다)프로그램의 출력을 thing1
이라는 프로그램으로 전달 thing2
하려면 다음을 수행하십시오.
thing1 > temp_file && thing2 < temp_file
어느 것
thing1
temp_file
thing2
키보드에있는 사람 temp_file
이 입력 내용을 입력 한 것처럼 가장하는 이라는 프로그램을 실행 하십시오.그러나 그것은 어수선하기 때문에 파이프를 더 간단한 방법으로 만들었습니다. thing1 | thing2
와 같은 일을thing1 > temp_file && thing2 < temp_file
의견의 질문에 대한 자세한 내용을 제공하도록 편집하십시오.
경우 >
수 모두 "프로그램에 전달"와 "파일에 쓸 '을 시도, 그것은 두 방향에서 문제가 발생할 수 있습니다.
첫 번째 예 : 파일에 쓰려고합니다. 덮어 쓰려는 해당 이름의 파일이 이미 있습니다. 그러나 파일은 실행 가능합니다. 아마도이 파일을 실행하여 입력을 전달하려고 시도했을 것입니다. 출력을 새 파일 이름으로 쓴 다음 파일 이름을 바꾸는 것과 같은 작업을 수행해야합니다.
두 번째 예 : Florian Diesch가 지적했듯이 시스템의 다른 이름과 동일한 이름 (실행 경로)에 다른 명령이 있으면 어떻게됩니까? 현재 폴더에 해당 이름의 파일을 만들려고한다면 막힐 것입니다.
셋째 , 명령을 잘못 입력하면 명령이 존재하지 않는다는 경고가 표시되지 않습니다. 입력 ls | gerp log.txt
하면 바로 알려줍니다 bash: gerp: command not found
. >
둘 다 의미하는 경우 단순히 새 파일을 만들 것입니다 (그런 다음 무엇을 해야할지 모르겠다는 경고 log.txt
).
less
예를 들어, 이라는 파일로 무언가를 리디렉션하려면 어떻게해야 합니까? thing | less
그리고 thing > less
그들은 다른 일을 같이 완벽하게 다릅니다. 당신이 제안하는 것은 모호성을 만듭니다.
tee
명령이 다르게 작동합니다. tee
화면 ( stdout
) 과 파일 모두에 출력을 씁니다 . 리디렉션은 파일 만 수행합니다.
리디렉션을 사용하는 것이 훨씬 더 어렵고 오류가 발생하기 쉬운 foo > bar
명명 된 명령이 있는지 여부에 따라 의미 가 결정 bar
됩니다. 파일로 리디렉션 할 때마다 먼저 대상 파일과 같은 이름의 명령이 있는지 확인해야했습니다.
bar
의 일부인 디렉토리에서 쓰는 경우에만 문제가됩니다 $PATH
. / bin과 같은 경우에는 문제가 될 수 있습니다. 그러나 그렇더라도 bar
쉘은 실행 파일을 찾을 bar
뿐만 아니라 실제로 실행할 수 있도록 실행 권한 세트를 가져야 합니다. 기존 파일을 덮어 쓰는 것이 우려되는 경우 noclober
셸 옵션을 사용하면 기존 파일을 리디렉션으로 덮어 쓰지 않아야합니다.
두 연산자 사이에는 중요한 차이점이 있습니다.
ls > log.txt
->이 명령은 출력을 log.txt 파일로 보냅니다.
ls | grep file.txt
->이 명령은 파이프 ( |
)를 사용하여 ls의 출력을 grep 명령으로 전송하고 grep 명령은 이전 명령이 제공 한 입력에서 file.txt를 검색합니다.
첫 번째 시나리오를 사용하여 동일한 작업을 수행해야한다면 다음과 같습니다.
ls > log.txt; grep 'file.txt' log.txt
따라서 파이프 (with |
)는 출력을 다른 명령으로 보내는 데 사용되는 반면 리디렉션 (with >
)은 출력을 일부 파일로 리디렉션하는 데 사용됩니다.
둘 사이에는 큰 구문상의 차이가 있습니다.
다음과 같은 리디렉션을 생각할 수 있습니다 cat [<infile] [>outfile]
. 이것은 순서가 중요하지 않음을 의미합니다 : cat <infile >outfile
와 동일합니다 cat >outfile <infile
. 당신은 다른 인수와 함께 리디렉션 혼합 수 cat >outfile <infile -b
및 cat <infile -b >outfile
모두 완벽하게 정상적으로입니다. 또한 하나 이상의 입력 또는 출력을 함께 묶을 수 있습니다 (입력은 순차적으로 읽히고 모든 출력은 각 출력 파일에 기록됩니다) cat >outfile1 >outfile2 <infile1 <infile2
. 리디렉션의 대상 또는 소스는 파일 이름 또는 스트림 이름 (최소한 bash에서 & 1과 같은) 일 수 있습니다.
그러나 파이프는 하나의 명령을 다른 명령과 완전히 분리하므로 인수와 함께 사용할 수 없습니다.
[command1] | [command2]
파이프는 command1의 표준 출력에 기록 된 모든 내용을 command2의 표준 입력으로 보냅니다.
배관과 방향 전환을 결합 할 수도 있습니다. 예를 들면 다음과 같습니다.
cat <infile >outfile | cat <infile2 >outfile2
첫 번째 cat
는 infile에서 행을 읽은 다음 각 행을 outfile에 쓰고 두 번째 행으로 보냅니다 cat
.
두 번째 cat
에서 표준 입력은 먼저 파이프 (infile의 내용)에서 읽은 다음 infile2에서 읽은 다음 각 줄을 outfile2에 씁니다. 이를 실행 한 후 outfile은 infile의 사본이되고 outfile2에는 infile과 infile2가 포함됩니다.
마지막으로, "여기서 문자열"리디렉션 (bash 패밀리 만 해당)과 백틱을 사용하여 실제로 예제와 비슷한 작업을 수행합니다.
grep blah <<<`ls`
같은 결과를 줄 것이다
ls | grep blah
그러나 리디렉션 버전은 먼저 ls의 모든 출력을 버퍼 (메모리)로 읽은 다음 한 번에 한 줄씩 grep하기 위해 해당 버퍼를 공급하는 반면 파이프 버전은 ls에서 각 줄을 가져옵니다. 그 줄을 grep에 전달하십시오.
echo yes 1>&2 2>/tmp/blah; wc -l /tmp/blah; echo yes 2>/tmp/blah 1>&2; wc -l /tmp/blah
또한 파일로의 리디렉션은 마지막 리디렉션 만 사용합니다. echo yes >/tmp/blah >/tmp/blah2
에 쓸 것 /tmp/blah2
입니다.
참고 :이 답변은 최신 메커니즘에 대한 본인의 이해를 반영하며,이 사이트와 unix.stackexchange.com 의 동료가 답변을 연구하고 읽은 결과를 반영 하며 시간이 지남에 따라 업데이트됩니다. 주저하지 말고 의견을 말하거나 개선을 제안하십시오. 또한 syscall이 strace
명령을 사용 하여 쉘에서 어떻게 작동하는지 보려고 제안합니다 . 또한 내부 또는 시스템 콜의 개념에 겁 먹지 마십시오. 쉘이 어떻게 작동하는지 이해하기 위해 그것들을 알거나 사용할 필요는 없지만 분명히 이해하는 데 도움이됩니다.
|
파이프는 디스크의 항목과 연관되어 있지 않으므로 inode 수의 디스크 파일 시스템이 없지만 ( 커널 공간의 pipefs 가상 파일 시스템에 inode가 있음 ) 경로 재 지정에는 종종 디스크 항목이 있고 이에 해당하는 파일이 포함됩니다. 아이 노드.lseek()
수 없으므로 명령이 일부 데이터를 읽은 다음 되감기를 할 수 없지만 리디렉션 >
하거나 <
일반적으로 파일 lseek()
일 수 있는 파일 인 경우 명령은 원하는대로 탐색 할 수 있습니다.dup2()
실제 데이터 흐름이 발생하는 파일 디스크립터의 사본을 제공하기 위해 후드 아래에 syscall을 사용 합니다.exec
기본 제공 명령을 사용 하여 리디렉션을 "전역 적으로"적용 할 수 있으므로 ( this 및 this 참조 ) exec > output.txt
모든 명령 을 수행하는 경우 output.txt
그 이후부터 쓰게됩니다 . |
파이프는 현재 명령 (단순 명령 또는 서브 쉘 유사 seq 5 | (head -n1; head -n2)
또는 복합 명령 을 의미)에만 적용됩니다 .파일에 대한 경로 재 지정이 수행되면 해당 파일에서 syscall을 사용 echo "TEST" > file
하고 ( 또한 참조 ) 파일 디스크립터를 가져 와서 파일 디스크립터로 전달하십시오 . 파이프 만을 사용 하고 콜.echo "TEST" >> file
open()
dup2()
|
pipe()
dup2()
명령이 실행되는 한 파이프와 리디렉션은 맹목적으로 쓰거나 내부적으로 조작 할 수있는 파일과 같은 파일 설명자입니다. 예 apt
를 들어 stdout에 쓰지 않는 경향이 있습니다. 리디렉션이 있다는 것을 알고 있다면).
이 두 메커니즘의 차이점을 이해하려면 필수 속성, 두 가지 역사 및 C 프로그래밍 언어의 근본을 이해해야합니다. 실제로, 파일 디스크립터가 무엇인지, dup2()
그리고 pipe()
시스템 호출이 어떻게 작동 하고 어떻게 작동 하는지 아는 것이 필수적 lseek()
입니다. 쉘은 이러한 메커니즘을 사용자에게 추상적으로 만드는 방법을 의미하지만 추상화보다 더 깊이 파고 들어가면 쉘 동작의 실제 특성을 이해하는 데 도움이됩니다.
데니스 리치의 기사에 따르면 예언 암각화 , 파이프는 유래 1964 내부 메모 에 의해 말콤 더글라스 맥 일로이 가 작업을 한 번에, 멀 틱스 운영 체제 . 인용문:
내 가장 큰 관심사를 간단히 말하면 :
- 정원 호스와 같은 프로그램을 연결하는 방법이 있어야합니다. 다른 방법으로 데이터를 마사지해야 할 때 다른 세그먼트의 나사가 필요합니다. 이것은 또한 IO의 방법입니다.
명백한 것은 프로그램이 디스크에 쓸 수 있었지만 출력이 클 경우 비효율적 이었다는 것입니다. 유닉스 파이프 라인 비디오 에서 Brian Kernighan의 설명을 인용하려면 :
첫째, 하나의 큰 대규모 프로그램을 작성할 필요가 없습니다. 이미 작업의 일부를 수행 할 수있는 기존의 작은 프로그램이 있습니다 ... 또 다른 방법은 처리중인 데이터의 양이 적합하지 않을 수 있다는 것입니다 운이 좋으면 메가 바이트 또는 두 개의 데이터가있는 파이프 라인이 있었기 때문에 파이프 라인이 전체 출력을 인스턴스화 할 필요가 없었던 것을 기억하십시오. .
따라서 개념적 차이는 명백합니다. 파이프는 프로그램이 서로 대화하게하는 메커니즘입니다. 리디렉션-기본 수준에서 파일에 쓰는 방법입니다. 두 경우 모두 쉘은이 두 가지를 쉽게 해주지 만, 후드 아래에는 많은 일들이 있습니다.
우리는 파일 디스크립터 의 개념으로 시작 합니다 . 파일 디스크립터는 기본적으로 열린 파일 (디스크 또는 메모리에있는 파일이든 익명 파일이든)을 정수로 표시합니다. 두 개의 표준 데이터 스트림 (stdin, stdout, stderr)은 각각 파일 디스크립터 0, 1 및 2입니다. 그들은 어디에서 왔니 ? 셸 명령에서 파일 디스크립터는 부모-셸에서 상속됩니다. 자식 프로세스는 부모의 파일 디스크립터를 상속합니다. 들어 데몬 은 상속 된 모든 파일 디스크립터를 닫고 / 또는 다른 장소로 리디렉션하는 것이 일반적이다.
리디렉션으로 돌아 가기 정말 무엇입니까? 쉘이 명령을 실행하기 전에 쉘에 의해 경로 재 지정이 수행되기 때문에 명령에 대한 파일 디스크립터를 준비하고 사용자가 제안한 위치를 지시하도록하는 메커니즘입니다. 출력 리디렉션 의 표준 정의 는
[n]>word
그건 [n]
파일 기술자 번호가있다. 당신이 할 때 echo "Something" > /dev/null
1 번 숫자가 암시 echo 2> /dev/null
됩니다.
후드 아래에서 이것은 dup2()
시스템 호출을 통해 파일 디스크립터를 복제하여 수행됩니다 . 하자 df > /dev/null
. 쉘은 자식 프로세스 생성됩니다 df
실행을하지만, 그 전에이 열립니다 /dev/null
파일 기술자 # 3으로하고, dup2(3,1)
파일 기술자 3의 복사본을 만드는 발행되고 복사 당신은 당신이 두 개의 파일이 방법을 알고 1. 될 것입니다 file1.txt
및 file2.txt
그리고 cp file1.txt file2.txt
두 개의 동일한 파일이 있지만 독립적으로 조작 할 수 있습니까? 그것은 여기서 일어나는 것과 똑같은 일입니다. 종종 당신은 실행하기 전에이 있음을 볼 수있다 bash
할 것 dup(1,10)
입니다 복사 파일 기술자 # 1을 만들기 위해 stdout
(그 사본 # 10 FD 것) 나중에 복원하기 위해. 내장 명령 을 고려할 때 중요 합니다.(쉘 자체의 일부이며 파일이 /bin
없거나 다른 곳에 파일이 없음 ) 또는 비 대화식 shell에 간단한 명령 인 경우, 쉘은 자식 프로세스를 생성하지 않습니다.
그리고 우리는 같은 일을 [n]>&[m]
하고 [n]&<[m]
. 이것은 파일 디스크립터를 복제하는 것인데, 현재와 동일한 메커니즘 dup2()
이 쉘 구문에 있으며 사용자가 편리하게 사용할 수 있습니다.
리디렉션에 대해주의해야 할 중요한 사항 중 하나는 순서가 고정되어 있지 않지만 쉘이 사용자가 원하는 것을 해석하는 방법에 중요하다는 것입니다. 다음을 비교하십시오.
# Make copy of where fd 2 points , then redirect fd 2
$ ls -l /proc/self/fd/ 3>&2 2> /dev/null
total 0
lrwx------ 1 user user 64 Sep 13 00:08 0 -> /dev/pts/0
lrwx------ 1 user user 64 Sep 13 00:08 1 -> /dev/pts/0
l-wx------ 1 user user 64 Sep 13 00:08 2 -> /dev/null
lrwx------ 1 runner user 64 Sep 13 00:08 3 -> /dev/pts/0
lr-x------ 1 user user 64 Sep 13 00:08 4 -> /proc/29/fd
# redirect fd #2 first, then clone it
$ ls -l /proc/self/fd/ 2> /dev/null 3>&2
total 0
lrwx------ 1 user user 64 Sep 13 00:08 0 -> /dev/pts/0
lrwx------ 1 user user 64 Sep 13 00:08 1 -> /dev/pts/0
l-wx------ 1 user user 64 Sep 13 00:08 2 -> /dev/null
l-wx------ 1 user user 64 Sep 13 00:08 3 -> /dev/null
lr-x------ 1 user user 64 Sep 13 00:08 4 -> /proc/31/fd
쉘 스크립팅에서 이들을 실용적으로 사용할 수 있습니다.
그리고 다른 많은.
pipe()
및dup2()
파이프는 어떻게 만들어 집니까? pipe()
syscall을 통해 입력 pipefd
의 두 항목 유형 int
(정수)으로 불리는 배열 (일명 목록) 을 입력으로 받습니다. 이 두 정수는 파일 설명자입니다. 는 pipefd[0]
파이프의 읽기 끝이하고 pipefd[1]
쓰기 종료 될 것입니다. 그래서에서 df | grep 'foo'
, grep
사본을 얻을 것이다 pipefd[0]
과 df
의 사본을 얻을 것이다 pipefd[1]
. 그러나 어떻게? 물론 dup2()
syscall 의 마법으로 . 이 df
예제에서 pipefd[1]
# 4 가 있다고 가정 해 봅시다 . 그래서 쉘이 자식을 만들고 dup2(4,1)
(내 cp
예제를 기억 하십니까?) execve()
실제로 실행 df
합니다. 당연히,df
파일 디스크립터 # 1을 상속 받지만 더 이상 터미널을 가리 키지 않지만 실제로 파이프의 쓰기 끝인 fd # 4를 인식하지 못합니다. 당연히 grep 'foo'
다른 수의 파일 디스크립터 를 제외하고 는 동일한 일이 발생 합니다.
이제 흥미로운 질문 : fd # 1뿐만 아니라 fd # 2를 리디렉션하는 파이프를 만들 수 있습니까? 예, 사실 |&
bash에서 수행하는 작업입니다. POSIX 표준을 지원하는 쉘 명령 언어를 필요로 df 2>&1 | grep 'foo'
그 목적을 위해 구문을하지만, bash
않습니다 |&
뿐만 아니라.
중요한 것은 파이프는 항상 파일 디스크립터를 처리한다는 것입니다. 디스크에 파일 이름이 있고 파일로 사용하지만 파이프처럼 동작하는 pipe 가 존재 FIFO
하거나 이름이 지정 됩니다. 그러나 |
파이프 유형은 익명 파이프로 알려져 있습니다. 파일 이름이 없습니다. 실제로는 두 개체가 서로 연결되어 있기 때문입니다. 우리가 파일을 다루지 않는다는 사실도 중요한 의미를 갖습니다. 파이프는 불가능 lseek()
합니다. 메모리 나 디스크에있는 파일은 정적입니다. 프로그램은 lseek()
syscall을 사용 하여 바이트 120으로 건너 뛰고 바이트 10으로 되돌아 간 다음 끝까지 계속 전달할 수 있습니다. 파이프는 정적이 아닙니다. 파이프는 순차적이므로 파이프에서 얻은 데이터를 되 감을 수 없습니다lseek()
. 파일이나 파이프에서 읽을 때 일부 프로그램이이를 인식하게하므로 효율적인 성능을 위해 필요한 조정을 수행 할 수 있습니다. 즉, 또는 prog
할 경우를 감지 할 수 있습니다 . 그 실제 사례는 tail 입니다.cat file.txt | prog
prog < input.txt
파이프의 다른 두 가지 흥미로운 속성은 리눅스에서 4096 바이트 인 버퍼를 가지고 있고 실제로 리눅스 소스 코드에서 정의 된 파일 시스템을 가지고 있다는 것입니다 ! 그들은 단순히 데이터를 전달하는 객체가 아니라 데이터 구조 자체입니다! 실제로 파이프와 FIFO를 모두 관리하는 pipefs 파일 시스템이 있으므로 파이프는 해당 파일 시스템에 inode 번호가 있습니다.
# Stdout of ls is wired to pipe
$ ls -l /proc/self/fd/ | cat
lrwx------ 1 user user 64 Sep 13 00:02 0 -> /dev/pts/0
l-wx------ 1 user user 64 Sep 13 00:02 1 -> pipe:[15655630]
lrwx------ 1 user user 64 Sep 13 00:02 2 -> /dev/pts/0
lr-x------ 1 user user 64 Sep 13 00:02 3 -> /proc/22/fd
# stdin of ls is wired to pipe
$ true | ls -l /proc/self/fd/0
lr-x------ 1 user user 64 Sep 13 03:58 /proc/self/fd/0 -> 'pipe:[54741]'
Linux 파이프는 리디렉션과 마찬가지로 단방향입니다. 일부 유닉스 계열 구현에는 양방향 파이프가 있습니다. 쉘 스크립팅의 마법이 있지만 Linux 에서도 양방향 파이프를 만들 수 있습니다.
pipe()
콜과 dup2()
.<<
, <<<
익명 (연결되지 않은) 임시 파일로 구현 bash
하고 ksh
있지만, < <()
익명 파이프를 사용합니다; /bin/dash
에 파이프를 사용합니다<<
. bash에서 <<, <<< 및 <<의 차이점 은 무엇입니까?를 참조하십시오 .다른 답변에 추가하기 위해 미묘한 의미 론적 차이도 있습니다. 예를 들어 파이프가 리디렉션보다 더 가깝게 닫힙니다.
seq 5 | (head -n1; head -n1) # just 1
seq 5 > tmp5; (head -n1; head -n1) < tmp5 # 1 and 2
seq 5 | (read LINE; echo $LINE; head -n1) # 1 and 2
첫 번째 예제에서 첫 번째 호출이 head
완료되면 파이프가 닫히고 seq
종료되므로 두 번째에 사용할 수있는 입력이 없습니다 head
.
두 번째 예에서 head는 첫 번째 행을 사용하지만 자체 stdin
파이프를 닫으면 다음 호출에서 사용할 수 있도록 파일이 열린 상태로 유지됩니다.
세 번째 예는 read
파이프 폐쇄를 피하기 위해 사용하는 경우 하위 프로세스 내에서 여전히 파이프를 사용할 수 있음을 보여줍니다 .
따라서 "스트림"은 데이터를 분류하고 (stdin 등) 두 경우 모두 동일하지만 파이프는 두 프로세스의 스트림을 연결합니다. 여기서 리디렉션은 프로세스와 파일 사이의 스트림을 연결합니다. 유사점과 차이점의 근원을 볼 수 있습니다.
추신. 당신이 그 예에 대해 궁금하거나 놀랐다면 trap
, 프로세스가 어떻게 해결되는지보기 위해 더 깊이 파고들 수 있습니다 .
(trap 'echo seq EXITed >&2' EXIT; seq 5) | (trap 'echo all done' EXIT; (trap 'echo first head exited' EXIT; head -n1)
echo '.'
(trap 'echo second head exited' EXIT; head -n1))
때로는 첫 번째 프로세스가 닫히기 전에 닫히기 1
도합니다.
또한 exec <&-
파이프 동작을 근사하기 위해 리디렉션에서 스트림을 닫는 데 사용 하는 것이 흥미로 웠습니다 (오류가 있음).
seq 5 > tmp5
(trap 'echo all done' EXIT
(trap 'echo first head exited' EXIT; head -n1)
echo '.'
exec <&-
(trap 'echo second head exited' EXIT; head -n1)) < tmp5`
read
첫 번째 줄만 사용 하기 때문에 세 번째 예제도 정확하지 않습니다 (1 바이트 for 1
및 newline). seq
총 10 바이트 (5 개의 숫자와 5 개의 줄 바꿈)로 전송됩니다. 따라서 파이프 버퍼에 8 바이트가 남아 있으므로 이것이 두 번째로 head
작동하는 이유 입니다. 파이프 버퍼에 여전히 사용 가능한 데이터가 있습니다. Btw, 0 바이트를 읽은 경우에만 헤드가 종료됩니다.head /dev/null
seq 5 | (head -n1; head -n1)
첫 번째 호출에서 파이프가 비워 지므로 파이프가 여전히 열린 상태이지만 두 번째 호출에 대한 데이터는 없음을 올바르게 이해 하고 head
있습니까? 파이프와 경로 재 지정의 동작의 차이는 헤드가 파이프에서 모든 데이터를 가져 오지만 파일 핸들에서 두 줄만 가져 오기 때문입니다.
strace
첫 번째 의견에서 내가 준 명령 으로 볼 수있는 것입니다 . 리디렉션을 사용하면 tmp 파일이 디스크에있어 탐색 가능합니다 ( lseek()
syscall 을 사용하기 때문에 -명령은 파일을 첫 번째 바이트에서 마지막 바이트까지 이동할 수 있지만 파이프는 순차적이며 탐색 할 수 없습니다. 따라서 헤드를 수행하는 유일한 방법은 작업은 먼저 모든 것을 읽을 수있다, 또는 파일이 큰 경우 -을 통해 RAM에 그 중 일부를 매핑 mmap()
전화 나는 한 번 내 자신했다. tail
파이썬에서, 정확히 같은 문제로 실행했습니다.
(...)
쉘이 내부의 각 명령에 대한 자체 stdin의 사본을 작성 한다는 점을 기억하는 것이 중요합니다 (...)
. 따라서 기술적으로 동일한 객체에서 읽습니다. 먼저 head
자체 stdin에서 읽는다고 생각합니다. 두 번째 head
는 자체 stdin이 있다고 생각합니다. 그러나 실제로 fd # 1 (stdin)은 동일한 fd의 복사본이며 파이프 끝에서 읽습니다. 또한 답변을 게시 했으므로 내용을 명확히하는 데 도움이 될 수 있습니다.
나는 오늘 C에서 이것에 대한 문제를 겪었다. 본질적으로 파이프는로 보낼 때도 리디렉션에 대한 의미가 다릅니다 stdin
. 실제로 차이점을 감안할 때 파이프가 아닌 다른 곳으로 가야 stdin
하므로 임의의 차등을 만들기 위해 stdin
호출 할 stdpipe
수 있습니다.
이걸 고려하세요. 파일이 있음에도 불구하고 한 프로그램 출력을 다른 프로그램으로 파이핑하면 fstat
0을 반환하는 것처럼 보입니다 . 파일을 리디렉션 할 때 적어도 데비안의 경우 (아니다 , 그리고 바닐라와 우분투 , 바닐라.st_size
ls -lha /proc/{PID}/fd
wheezy
stretch
jessie
14.04
16.04
당신이 경우 cat /proc/{PID}/fd/0
리디렉션에 당신은 당신이 원하는만큼 여러 번 읽기를 반복 할 수 있습니다. 파이프로이 작업을 수행하면 두 번째로 작업을 연속으로 실행할 때 동일한 출력을 얻지 못합니다.
thing1 > temp_file && thing2 < temp_file
파이프로 더 쉽게 할 것을 언급 했습니다. 그러나 왜 안 다시 사용>
예 :이 작업을 수행하는 연산자thing1 > thing2
명령에thing1
와thing2
? 왜 여분의 연산자|
입니까?