NULL로 끝나는 레코드에 comm 사용

NULL로 끝나는 레코드에 comm 사용

오버 인답변list2다른 질문으로, 나는 다음과 같은 구조를 사용하여 에 나타나지 않는 파일을 찾고 싶었습니다 list1.

( cd dir1 && find . -type f -print0 ) | sort -z > list1
( cd dir2 && find . -type f -print0 ) | sort -z > list2
comm -13 list1 list2

그러나 내 버전에서는 NULL로 끝나는 레코드를 처리할 수 없기 때문에 난관에 부딪혔습니다 comm. (일부 배경 정보: 계산된 목록을 에 전달하므로 rm특히 새 줄이 포함될 수 있는 파일 이름을 처리할 수 있기를 원합니다.)

쉬운 예제를 원한다면 이것을 시도하십시오

mkdir dir1 dir2
touch dir1/{a,b,c} dir2/{a,c,d}
( cd dir1 && find . -type f ) | sort > list1
( cd dir2 && find . -type f ) | sort > list2
comm -13 list1 list2

NULL로 끝나는 줄이 없으면 여기서 출력은 ./d에서만 나타나는 단일 요소입니다 list2.

find ... -print0 | sort -z목록을 생성하는 데 사용할 수 있기를 바랍니다 .

에는 나타나지만 commNULL로 종료되는 레코드를 출력하는 것과 동일한 것을 가장 잘 다시 구현할 수 있는 방법은 무엇입니까 ?list2list1

답변1

GNU comm(GNU coreutils 8.25 기준)에는 이제 이에 대한 -z/ 옵션이 있습니다.--zero-terminated

이전 버전의 GNU에서는 commNUL과 NL을 교체할 수 있어야 합니다.

comm -13 <(cd dir1 && find . -type f -print0 | tr '\n\0' '\0\n' | sort) \
         <(cd dir2 && find . -type f -print0 | tr '\n\0' '\0\n' | sort) |
  tr '\n\0' '\0\n'

이 방법은 comm줄 바꿈으로 구분된 레코드에서도 작동하지만 NUL로 인코딩된 입력의 실제 줄 바꿈을 사용하므로 줄 바꿈이 포함된 파일 이름으로 여전히 안전합니다.

CGNU 시스템과 대부분의 UTF-8 로케일에는 동일하게 정렬되어 여기서 문제를 일으킬 수 있는 다른 문자열이 있기 때문에 로케일을 다음으로 설정할 수도 있습니다 .

이는 매우 일반적인 트릭입니다(참조:일치하는 라인 반전, NUL로 구분) 의 또 다른 예는 comm입력에 NUL을 지원하는 유틸리티가 필요하며 GNU 시스템 외부에서는 상대적으로 드뭅니다.


¹ 예:

$ touch dir1/{①,②} dir2/{②,③}
$ comm -12 <(cd dir1 && find . -type f -print0 | tr '\n\0' '\0\n' | sort) \
           <(cd dir2 && find . -type f -print0 | tr '\n\0' '\0\n' | sort)  
./③
./②
$ (export LC_ALL=C
    comm -12 <(cd dir1 && find . -type f -print0 | tr '\n\0' '\0\n' | sort) \
             <(cd dir2 && find . -type f -print0 | tr '\n\0' '\0\n' | sort))
./②

(2019년 편집: 최신 버전의 GNU libc에서는 ① ② ③의 상대적 순서가 수정되었지만 다음을 사용할 수 있습니다.

관련 정보