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목록을 생성 하고 싶습니다 .

comm에 나타나지만 나타나지 않는 NULL 종료 레코드를 출력하는 동등한 것을 다시 구현하는 가장 좋은 방법은 무엇입니까 ?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로 인코딩되므로 줄 바꿈이 포함된 파일 이름을 안전하게 처리할 수 있습니다.

C적어도 GNU 시스템과 대부분의 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에서는 ① ② ③의 상대적 순서가 수정되었지만 다음을 사용할 수 있습니다.

관련 정보