ファイルへの重複したハードリンクをすべて削除する方法は?

ファイルへの重複したハードリンクをすべて削除する方法は?

rsnapshot同じディレクトリ構造の複数のスナップショットを含み、同じファイルがすべてハードリンクに置き換えられたディレクトリツリーが作成されました。

これらのハードリンクの重複エントリをすべて削除し、各ファイルのコピーを1つだけ保持したいと思います。これにより、後で同じファイルに2回触れることなく、すべてのファイルをソートされたアーカイブに移動できます。

これを行うためのツールはありますか?
これまで、重複項目を見つけることができるツールだけが見つかりました。作るこれに代わるハードリンク...
すべてのファイルとそのinode番号をリストし、重複排除と削除を直接実装できると思いますが、ここではホイールを再発明したくありません。

答え1

最後に、これを手動で行うことはそれほど難しくありません。スティーブンそしてジェノイドのようなヒントといくつかの事前経験find
FreeBSDのGNU以外のツールと連携するには、いくつかのコマンドを調整する必要がありました。 GNUにはそれを置き換えるオプションがfindありますが、FreeBSDはそうではありません。-printf-exec statfind

# create a list of "<inode number> <tab> <full file path>"
find rsnapshots -type f -links +1 -exec stat -f '%i%t%R' {} + > inodes.txt

# sort the list by inode number (to have consecutive blocks of duplicate files)
sort -n inodes.txt > inodes.sorted.txt

# remove the first file from each block (we want to keep one link per inode)
awk -F'\t' 'BEGIN {lastinode = 0} {inode = 0+$1; if (inode == lastinode) {print $2}; lastinode = inode}' inodes.sorted.txt > inodes.to-delete.txt

# delete duplicates (watch out for special characters in the filename, and possibly adjust the read command and double quotes accordingly)
cat inodes.to-delete.txt | while read line; do rm -f "$line"; done

答え2

複数のリンクを持つ索引ノードを見つけるには、次のようにします。

 find . -exec stat -c '%i' {} \; | sort -n | uniq -d

その後、そのリストを繰り返すことができます。

 find -inum {inode_number}

このinodeを共有するファイルをリストします。どちらを削除するかはあなた次第です。

答え3

すべてのファイルが単一のディレクトリ階層のハードリンクのみを持っていることがわかっている場合は、単に次のことができます。

find inputdir -type f -links +1 -exec rm {} \;

その理由は、rm {} \;ファイルをすぐに削除するとstat()1つ以上の数が返されるためです。したがって、同じ inode の他の部分のハードリンク数は 1 ずつ減らされ、そのファイルが唯一のコピーである場合、最後のファイルでrmfind 実行時にそのファイルに対しては find は実行されませんstat()

ファイルにinputdirこのコマンド以外のハードリンクコピーがある場合は注意してください。すべてのコピーが削除されます。階層内でinputdir

答え4

リントハードリンクを含む重複エントリが見つかり、削除されます。現在削除オプションはありませんただハードリンク。削除は自動的に生成されたシェルスクリプトを介して行われ、削除する前にスクリプトを確認できます。

通常、ハードリンクモードで冗長ファイル検出器(fdupes -Hなど)を使用するときは注意してください。時には、ファイルを自分の重複として誤って識別する可能性があるためです(「パスの冗長性」の説明を参照)。ここ)。

関連情報