bash_06 중간 파일 없이 명령어 출력을 파일처럼 다루기

 
  • 출처 : 유닉스 리눅스 쉘스크립트 예제사전_한빛미디어

명령어: 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 최신판을 설치하기 바랍니다.