- 출처 : 유닉스 리눅스 쉘스크립트 예제사전_한빛미디어
명령어: find, sort, comm
키워드: 파일 목록, 디렉터리 비교
사용처: 두 디렉터리가 비슷한 구조일 대 한쪽에만 있거나 양쪽에 있는 파일을 보기 좋게 목록화하고 싶을 때
실행예제
$ ./find-comm.sh
./dav.conf
./default.conf
./info.conf
./mpm.conf
./ssl.conf
./userdir.conf
./vhosts.conf
스크립트
#!/bin/sh
# 비교할 디렉터리명
dirA="dir1"
dirB="dir2"
# dir1/과 dir2/ 파일 목록 차이를 조사하기
( cd dir1; find . -maxdepth 1 -type f -print | sort ) > dir1-file.lst #--- 1
( cd dir2; find . -maxdepth 1 -type f -print | sort ) > dir2-file.lst #--- 1
comm dir1-file.lst dir2-file.lst #---------------------------------------- 2
해설
이 스크립트는 현재 디렉터리 아래이 있는 dir1과 dir2 디렉터리의 파일을 조사해서 아래에 조건에 맞게 나눠서 출력합니다.
- dir1에만 있는 파일
- dir2에만 있는 파일
- dir과 dir2 양쪽에 있는 파일
을 나눠서 출력합니다. 출력은 탭으로 정렬해서 1, 2, 3 순서대로 표시됩니다. 실행 예제에서는 dav.conf와 vhosts.conf가 디렉터리 dir1에만 있고 ssl.conf는 dir2에만 있고, 나머지 파일은 양쪽 디렉터리에 존재합니다. 실제로 이 예제를 실행할 때는 셸 변수 dirA와 dirB를 비교하고 싶은 디렉터리로 변경하기 바랍니다.
1
에서 각각 서브 디렉터리마다 파일 목록을 임시 파일에 출력합니다. 여기에서는 디렉터리 이동과 리다이렉트 출력 모두를 서브셸에서 합니다. 서브셸을 쓰는 것은 cd 명령어로 현재 디렉터리를 이동하고 나서 원래 디렉터리로 자동으로 돌아오기 위해서입니다.
우선 1
에서는 디렉터리 파일 목록을 만들 때 find 명령어로 -type f를 지정해서 디렉터리를 제외하고 보통 파일만 지정합니다. 그리고 -maxdepth 1로 두 단계 이상 깊은 디렉터리 안에 있는 파일을 제외하고 서브 디렉터리 바로 아래 있는 파일만 대상으로 삼습니다.
디렉터리 dir1 파일 목록을 tempfile1.lst로, 디렉터리 dir2 파일 목록을 tempfile2.lst로 출력했으므로 이 파일을 비교합니다.
2
에서 comm 명령어로 두 디렉터리 파일 목록 차분을 출력합니다. comm 명령어는 파일 내용을 비교하는 명령어도 두 입력 파일을 읽어서 같은 줄과 다른 줄을 각각 표시합니다. comm 명령어 실행 예제 결과는 아래와 같습니다.
- comm 명령어는 두 파일을 비교함
$ comm file1 file2 1 2 3 4 5 6 7
여기서 각 열의 의미는 다음과 같습니다.
- 첫 열은 file1 에만 있는 행 출력
- 두 번재 열은 file2에만 있는 행 출력
- 세 번째 열은 양쪽에 공통된 행 출력
그리고 comm 명령어를 사용할 때는 입력 파일이 정렬되어 있어야 합니다. 따라서 예제에서는 1
에서 find를 실행한 다음 sort 명령어로 정렬하고, 임시 파일에 출력합니다. 이렇게 디렉터리 파일 목록을 comm 명령어로 비교해서 각 디렉터리에 있는 파일을 비교합니다.
주의사항
-
이렇게 두 디렉터리 사이에 파일 목록 차이를 확인한 다음 디렉터리끼리 파일을 동기화하고 싶을 때가 있습니다. 두 디렉터리 간 파일을 동기화하려면 rsync 명령어가 편리합니다.
- comm 명령어는 지정한 열만 출력할 수도 있습니다. 이때 표시하고 싶은 열을 -1 또는 -2처럼 지정합니다. 양족 파일에 존재하는 줄만 표시하고 싶다면 다음처럼 -12로 세 번째 열만 표시하면 됩니다.
comm -12 file1 file2
-
comm 명령어 종료 스테이터스는 diff 명령어와 약간 다르므로 주의해야 합니다. diff 명령어 종료 스테이터스는 다음과 같습니다.
- 두 파일이 동일하면 종료 스테이터스는 0
- 두 파일에 차이가 있으면 1
- 파일이 없거나 에러 발생 시 2
-
즉 diff 명령어는 종료 스테이터스가 0 또는 1일 때 두 파일에 차이가 있는지 없는지 판단하는 것이 일반적입니다.
- 한편, comm 명령어는 두 파일의 차이가 있든지 없든지 정상 종료라면 종료 스테이터스로 0을 돌려줍니다. comm 명령어가 종료 스테이터스로 0이 아닌 값을 돌려주면 파일이 발견되지 않는 등 에러가 발생했을 때 뿐입니다. 따라서 comm 명령어 종료 스테이터스를 확인해서 조건 분기로 스크립트를 만들 때는 diff 명령어와 다르다는 사실에 유의하기 바랍니다.