findのパイプ出力をtarに:アーカイブのファイルに繰り返しリンクしない

findのパイプ出力をtarに:アーカイブのファイルに繰り返しリンクしない

findの出力をパイプで接続すると、tar各ファイルへの2つのリンクが結果のアーカイブに表示されます。tarディレクトリに直接適用する場合はそうではありません。重複リンクを避けることはできますか?

例は次のとおりです。

$ mkdir tmp
$ for i in {1..3}; do echo "$i" > "tmp/$i"; done
$ ls tmp
1  2  3
$ tar -cvvf tmp.tar tmp | sort
drwxr-xr-x usr/grp   0 2019-05-02 15:09 tmp/
-rw-r--r-- usr/grp   2 2019-05-02 15:09 tmp/1
-rw-r--r-- usr/grp   2 2019-05-02 15:09 tmp/2
-rw-r--r-- usr/grp   2 2019-05-02 15:09 tmp/3
$ find tmp | tar -T - -cvvf tmp.tar | sort
drwxr-xr-x usr/grp   0 2019-05-02 15:09 tmp/
hrw-r--r-- usr/grp   0 2019-05-02 15:09 tmp/1 link to tmp/1
hrw-r--r-- usr/grp   0 2019-05-02 15:09 tmp/2 link to tmp/2
hrw-r--r-- usr/grp   0 2019-05-02 15:09 tmp/3 link to tmp/3
-rw-r--r-- usr/grp   2 2019-05-02 15:09 tmp/1
-rw-r--r-- usr/grp   2 2019-05-02 15:09 tmp/2
-rw-r--r-- usr/grp   2 2019-05-02 15:09 tmp/3

これはGNU tar 1.26を使用して行われた。

ベストアンサー1

SteelDriverが指摘したように、問題はtarディレクトリ内のファイルだけを受け取るのではなく、ディレクトリ自体も受け取ることです。デフォルトの動作はtarディレクトリを介して再帰するため、ディレクトリ内の各エントリは2番目に追加されます(一度は明示的にファイルを提供し、一度は明示的に提供されたディレクトリを介して再帰)。解決策は、(1)ディレクトリを提供しない、または(2)再帰を無効にすることです。

最初のものは次のとおりです。

$ find tmp -type f -print0 | sort -z | tar --null -T - -cvvf tmp.tar
-rw-r--r-- usr/grp     2 2019-05-02 17:06 tmp/1
-rw-r--r-- usr/grp     2 2019-05-02 17:06 tmp/2
-rw-r--r-- usr/grp     2 2019-05-02 17:06 tmp/3

2番目のケース(完全にネストされたディレクトリ構造を再現したいので必要です)は、単に再帰を無効にすることです。

$ find tmp -print0 | sort -z | tar --no-recursion --null -T - -cvvf tmp.tar
drwxr-xr-x usr/grp     0 2019-05-02 17:06 tmp/
-rw-r--r-- usr/grp     2 2019-05-02 17:06 tmp/1
-rw-r--r-- usr/grp     2 2019-05-02 17:06 tmp/2
-rw-r--r-- usr/grp     2 2019-05-02 17:06 tmp/3

おすすめ記事