Pipeline, Redirection; 무슨 차이?

아무 생각없이 수십년(까지는 아니더라도..)을 사용해왔던 pipeline 과 redirection. 무슨 차이가 있는 건지, 제대로 이해를 못했었다. 적어도 며칠 전까지는.
잊기 전에 정리한다.

이 기능을 이해하기 위해선 Standard Streams 에 대한 지식이 필요하다. 복잡한 내용은 위키피디어를 참고하고, 아주 간단하게 이렇게 정의할 수 있겠다.

  • Standard Input : 키보드로 입력한 내용
  • Standard Output : 화면에 보여진 정상출력(오류 제외) 내용

이걸 잊지말고, 다음 내용을 보자.

Pipeline 은 Standard Output 을, Standard Input 으로 변환 후 다음 이어지는 프로그램의 인수로 넘겨주라는 뜻이다.

ls -l | more 를 해석해보자면, ls -l 의 결과(stdout)를 more 에 stdin 으로 넘기라는 뜻이 된다.
이 때 중요한 점! Pipeline 뒤에 나오는 명령어는 반드시 인수로 stdin 을 지원해야 한다. 뒤 명령이 stdin 을 지원하지 않는 경우, 원하는 결과가 나오지 않게 된다.

ls -l > list.txt 는, stdout 으로 나온 ls 의 결과를 디스플레이 장치에 출력하지 않고, list.txt 라는 파일로 ‘바꾸라’는 명령이 된다.


예전 글을 다시 되돌려보자.

여기에 나온 예를 끄집어내보면,

ls -l /etc | gzip > foo.txt.gz

이거, 처음에는 전혀 이해가 되지 않았고, 오랜만에 다시 보면, 여전히 생소할 때가 많다.

저 명령이 원하는 최종 결과는 이렇다.
ls -l /etc 결과를 gzip 으로 압축하여 foo.txt.gz 으로 만든다.
기존에 알고 있던 방식(초보자 수준)으로 이 작업을 완료하려면 이런 절차가 필요하다.

ls -l > foo.txt
gzip foo.txt

이러면 foo.txt.gz 파일이 만들어진다. 물론, gzip 은 원 파일(foo.txt)을 삭제하므로, foo.txt.gz 만 남긴 하지만, 어쨌든 명령은 두 번을 수행해야 한다.

저 작업을 한 줄로 줄이면, 위에 나온 명령이 된다. Pipeline 과 Redirection 을 모두 사용했기 때문에, (처음 볼 때는) 다소 생소하고, 이해하기가 어렵다. 그러나, 익숙해지면 오히려 더 편할 수도 있다.

먼저, gzip 은 stdin 을 지원한다는 사실을 알고 있어야 한다.
ls -l 로 생성된 stdout 을, | 을 통해 stdin 으로 바꾼다. 그 문자열을 gzip 이 받아 압축을 하게 되는데, 여기서 마지막 문제가 생긴다.

gzip 은 압축한 내용을 어디로 출력해야 하나?
어떻게 출력할 지 지정하지 않았으므로, 당연히 stdout 이 되어야 할텐데, 이럴 경우 gzip 은 오류를 발생한다. 그도 그럴 것이, 압축을 한 결과는 당연히 파일이 되어야 의미가 있지, 그것을 화면으로 뿌려봐야 써먹을 데가 전혀 없다.
만약, 강제로 그렇게 하고 싶다면 이렇게 하면 되긴 된다.

ls -l /etc | gzip -f

위에서 pipeline 뒤에 오는 명령어는 반드시 stdin 을 지원해야 한다고 했다. gzip 은 stdin 을 당연히 지원한다.
그러나 7za 는? 지원하긴 하지만, 기본 지원은 되지 않는다.

ls -l /etc | 7za a aaa.7z

이 명령은, ls 의 결과를 aaa.7z 에 추가하는 게 아니고, 7za 가 실행된 디렉토리의 모든 파일(및 디렉토리)을 압축하여 aaa.7z 를 생성한다.

gzip 과 동일한 결과를 만들기 위해서는? stdin 을 사용한다고 명시해줘야 한다.

ls -l /etc | 7za a -si aaa.7z

이러면 ls 결과가 aaa.7z 에 추가된다. (이 압축파일 내에는 aaa 라는 텍스트 파일이 들어있다.)

이렇듯, Pipleline 뒤에 오는 명령은 stdin 을 지원해야 함을 잊지 말자.

그리고, 더욱 중요하며, 잊지 말아야할 것!
stdin 은 그냥 문자열이다!! 경로로 사용하고 싶다면 xargs 를 사용해야 한다.

안녕하세요. 글 남겨주셔서 고맙습니다.