减少硬链接数量的方便脚本?

减少硬链接数量的方便脚本?

我正在将一个大型文件集从具有较高_PC_LINK_MAX(每个 inode 的最大硬链接数)的文件系统转换为较低的文件系统。

特别是,我正在使用 Amazon EFS,它的最大值为 175,如上所述这里

因此,我希望输入是一组经过重新调整的链接数高达 250 的文件,以便 inode 被拆分,这样每个文件的最大链接数为 100 个。

是否有一种巧妙的调用hardlink 可以做到这一点?或者也许有一个选项rsync -aH或可能cp -a有帮助?

...否则,一些黑客行为是有序的...

答案1

情况很棘手。想象一下最大链接是 5 个,并且您有 12 个文件 a01全部a12硬链接在一起。您需要拆分a01..a05a06..a10a11..a12其中a06a07等仍然硬链接在一起,但不是a01

这是一个 bash 脚本,rsync它在我的系统上的示例源目录 ( src=/usr/libexec/git-core/) 上运行,该目录有 110 个硬链接。它通过该函数模拟max目标目录中最多 50 个 links( ) 。在真实的情况下,你会忽略realdestsim链接太多错误,并且不使用该功能。

rsync -ni在初始正常 rsync (有错误)之后,通过使用将函数中的文件名提取calctodo到 中来创建丢失文件的列表/tmp/todo

然后有一个循环rsync,我们再次忽略丢失的文件链接太多2*175错误(如果原始目录中有多个链接,则会出现错误)。成功创建的文件之间是硬链接的。计算出新的丢失文件列表。重复此操作,直到没有更多文件为止。

src=/usr/libexec/git-core/
realdest=/tmp/realdest
#rm -fr "$realdest"
max=50
sim(){
    find ${1?} -links +$max |
    sed "1,${max}d" |
    xargs --no-run-if-empty rm
}
calctodo(){
    sed -n '/^hf/{ s/[^ ]* //; s/ =>.*//; p }' >/tmp/todo
}

rsync -aHR   "$src" "$realdest"; sim "$realdest"
rsync -niaHR "$src" "$realdest" | calctodo

while  [ -s /tmp/todo ]
do  mv /tmp/todo /tmp/todo.old
    rsync -aHR  --files-from=/tmp/todo.old / "$realdest"; sim "$realdest"
    rsync -niaHR --files-from=/tmp/todo.old / "$realdest" | calctodo
done

如果您的文件名带有“=>”、换行符等,您可能需要修改此设置。


请注意,您可以通过以下方式找到文件系统支持的最大链接数:

getconf LINK_MAX /some/directory

相关内容