如何仅“du”未被其他地方硬链接的文件占用的空间?

Tob*_*ler 14 hard-link disk-usage

采用rsync --link-dest了节省空间的快照,我怎么能弄清楚我多少空间实际保存?或更一般的:

仅考虑在目录结构之外的其他地方没有硬链接的文件,如何确定目录使用了多少空间?换一种方式提问:删除该目录后实际会释放多少空间?(du -hs会撒谎。可能包括硬链接本身所需的空间)

ang*_*gus 9

假设没有内部硬链接(也就是说,每个具有 1 个以上硬链接的文件都从树外部链接),您可以执行以下操作:

find . -links -2 -print0 | du -c --files0-from=-
Run Code Online (Sandbox Code Playgroud)

编辑这是我在评论中勾画的内容,已应用。只有没有du; du没有必要感谢@StephaneChazelas 的注意。解释在最后。

( find . -type d -printf '%k + ' ; \
  find . \! -type d -printf '%n\t%i\t%k\n' | \
    sort | uniq -c                         | \
    awk '$1 >= $2 { print $4 " +\\" }' ; \
  echo 0 ) | bc
Run Code Online (Sandbox Code Playgroud)

我们所做的是创建一个字符串,其中包含每个相关文件的磁盘使用情况(以 KB 为单位),用加号分隔。然后我们将那个大的补充喂给bc

第一次find调用对目录执行此操作。

第二个find打印链接计数、inode 和磁盘使用情况。我们传递该列表sort | uniq -c以获取(在树中出现的次数、链接计数、inode、磁盘使用情况)的列表。

我们通过列表传递awk,并且,如果第一个字段(出现次数)大于或等于第二个(硬链接数),这意味着没有从树外部指向此文件的链接,然后打印第四个字段(磁盘使用),带有一个加号和一个反斜杠。

最后我们输出 a 0,因此公式在语法上是正确的(否则会输入+)并将其传递给bc。呼。

(但我会使用更简单的第一种方法,如果它给出了足够好的答案。)


Sté*_*las 5

基本上,您需要获取所有文件(非目录)的 inode 编号和链接数,将该链接数与每个 inode 的出现次数进行比较,如果它们不同,则排除该文件。

假设它们都在同一个文件系统上,这样的事情应该可以工作(使用 GNU find):

find . -type d -printf '%k\n' -o -printf '%i %n %k\n' |
   awk '
     NF==1{t+=$0; next}
     {n1[$1]=$2; n2[$1]++; s[$1]=$3}
     END {
       for (i in n1)
         if (n1[i] == n2[i])
           t+=s[i]
       print t
     }'
Run Code Online (Sandbox Code Playgroud)


tuk*_*k0z 5

du实际上不会说谎;)它解析给它的目录,仅计算指向它遇到的同一 inode 的所有硬链接中的第一个。

如果您询问du它仅在一个目录中看到什么,它并不关心是否有其他硬链接指向相同的内容:

$ du -h daily.0 && du -hc daily.1
29G /daily.0
29G /daily.1
Run Code Online (Sandbox Code Playgroud)

现在将其目录放在同一行上(从最近的 rsync 增量备份开始--link-dest):

$ du -hc daily.0 daily.1
29G /daily.0
364M /daily.1
29G total
Run Code Online (Sandbox Code Playgroud)

或整个备份目录:

$ du -hc --max-depth=1 /snapshots
29G /daily.0
364M /daily.1
537M /daily.2
333M /daily.3
30G total
Run Code Online (Sandbox Code Playgroud)

“daily.1”中引用已在“daily.0”中引用的 inode(又名“真实”文件)的任何文件将不被计算在内。

因此,删除 daily.1 将在您的设备上节省 364MB 的空间。

消除