- 출처 : 유닉스 리눅스 쉘스크립트 예제사전_한빛미디어
명령어: comm
키워드: 프로세스 치환, 이름 파이프, FIFO
사용처: 중간 파일을 만들지 않고 명령어 출력 결과를 그대로 파일처럼 다루고 싶을 때
실행예제
$ ./process-subst.sh
app.log.20140201
app.log.20140202
app.log.20140203
app.log.20140204
app.log.20140205
myapp
obj.conf
obj.conf는 dir1에만 있고 app.log.20140205는 dir2에만 있음
스크립트
#!/bin/bash
# 비교할 두 디렉터리 정의
dir1="/var/tmp/backup1" #------------------------ 1
dir2="/var/tmp/backup2" #------------------------ 1
# comm 명령어로 출력을 비교. 중간 파일을 만들지 않아도
# 프로세스 치환으로 처리 가능
comm <(ls "$dir1") <(ls "$dir2") #--------------- 2
해설
이 스크립트는 두 디렉터리 내부의 파일 목록을 비교해서 그 차이를 표시합니다. comm 명령어를 중간 파일을 만들지 않고 bash 프로세스 치환(Process Substitution) 표기법으로 처리합니다.
bash 프로세스 치환이란 명령어 입력과 출력을 FIFO(이름 파이프, named pipe)와 파일 디스크립터를 나타내는 /dev/fd 이하의 디바이스 파일에 접속해서 실행하는 기능입니다. 명령어 출력 결과를 파일로 다른 명령어에 넘기려며 다음과 같이 사용합니다.
-
프로세스 치환 사용법
명령어1 < (명령어2)
일반적으로 파일을 대상으로 하는 명령어를 실행할 때 중간 파일을 작성하지 않고 처리하는 용도가 많을 것입니다. 다음 예에서는 ls 명령어 실행 결과를 파일로 보고 commandA를 실행합니다.
commandA <(ls -alF)
예제에서는 ls 명령어의 결과를 comm 명령어로 비교할 대상 목록 파일로 쓰고자 프로세스 치환을 사용합니다. 우선 1
에서 비교할 두 디렉터리를 정의합니다. 두 디렉터리 내부 파일 목록을 비교하는 경우를 가정합니다. 2
에서 프로세스 치환을 써서 두 ls 명령어 결과를 비교합니다. comm 명령어는 원래 다음처럼 두 파일을 인수로 받습니다.
comm a.txt b.txt
하지만 2
는 두 파일을 프로세스 치환으로 지정하면 명령어 결과를 그대로 이용할 수 있습니다.
프로세스 치환을 사용하지 않으면 다음처럼 두 ls 명령어 결과를 일단 임시 파일에 출력하고, 그걸 비교한다는 번거로움이 있습니다. 프로세스 치환을 사용하면 이런 임시 파일을 만들지 않아도 쉽게 작업할 수 있습니다.
ls "$dir" > dir1.tmp
ls "$dir2" > dir2.tmp
comm dir1.tmp dir2.tmp
이렇게 해서 comm 명령어 결과로 ‘디렉터리 $dir1에만 있는 파일’, ‘디렉터리 $dir2에만 있는 파일’, ‘양쪽에 있는 파일’로 나눠서 출력할 수 있습니다. 프로세스 치환은 그 외에도 파일을 대상으로 하는 명령어로 응용할 수 있는 표기법입니다.
주의사항
-
프로세스 치환 표기법 <(명령어)는 언뜻 보면 ‘입력 리다이렉트와 서브셸’ 처럼 보이지만 그렇지 않습니다. 어디까지나 <(명령어)처럼 서로 붙여써야 프로세스 치환표기법이 됩니다. 예를 들어
2
에서 다음처럼 괄호 앞에 스페이스를 넣으면 에러가 발생하므로 주의해야 합니다.comm < (ls "$dir1") < (ls "$dir2")
-
프로세스 치환은 이 예에서 본 것처럼 입력을 연결하는 처리와 반대로 출력을 연결하는 >(명령어)라는 표기법이 있습니다. 이것은 처리 결과를 표준 출력에는 출력하지 않고 파일에 직접 쓰는 프로그램처럼 파이프 처리하고 싶을 때 이용할 수 있습니다. mu-calc 명령어가 직접 결과를 지정한 파일에 출력하는 명령어라고 가정했을 때, 다음처럼 쓰면 결과를 파일이 아니라 표준 출력으로 줄 번호와 함께 표시할 수 있습니다.
my-calc >(cat -n)
-
FreeBSD 버전에 따라서는 프로세스 치환이 제대로 동작하지 않는 경우도 있습니다. 그때는 ports에서 bash 최신판을 설치하기 바랍니다.