我有一个由 创建的目录树rsnapshot
,其中包含同一目录结构的多个快照,所有相同的文件都被硬链接替换。
我想删除所有这些硬链接重复项,并只保留每个文件的一个副本(这样我以后就可以将所有文件移动到排序的存档中,而不必两次触摸相同的文件)。
有没有一个工具可以做到这一点?
到目前为止,我只找到了可以查找重复项的工具创造硬链接来替换它们......
我想我可以列出所有文件及其索引节点号并实现重复数据删除和删除自己,但我不想在这里重新发明轮子。
答案1
最后,基于以下内容,手动执行此操作并不难史蒂芬的和类xenoid的提示和一些先前的经验find
。
我必须调整一些命令才能与 FreeBSD 的非 GNU 工具一起使用 - GNUfind
有-printf
可以替换 的选项-exec stat
,但 FreeBSDfind
没有。
# 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,如果该文件是唯一的副本,则rm
当 find 对最后一个文件运行时,将不会对该文件运行stat()
。
请注意,如果任何文件在外部有硬链接副本inputdir
此命令之外具有硬链接副本将删除所有副本在等级制度内inputdir
!