
終わりました答え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 終了レコードを出力すると同等のものを最も効果的に再実装するにはどうすればよいでしょうか?list2
list1
答え1
GNU comm
(GNU coreutils 8.25 以降) には、そのための-z
/--zero-terminated
オプションが追加されました。
GNU の古いバージョンではcomm
、NUL と 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の新しいバージョンでは、①②③の相対的な順序は修正されていますが、