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 では、① ② ③ の相対的な順序が修正されていますが、以下を使用できます。

おすすめ記事