为什么ls -l中的“总计”与列出的文件大小总和不符?

151

为什么ls -l命令的输出中总计显示为64而不是所有列出的文件的26078

    $ ls -l ~/test/ls
    total 64
    -rw-r--r--   1 root root   15276 Oct  5  2004 a2ps.cfg
    -rw-r--r--   1 root root    2562 Oct  5  2004 a2ps-site.cfg
    drwxr-xr-x   4 root root    4096 Feb  2  2007 acpi
    -rw-r--r--   1 root root      48 Feb  8  2008 adjtime
    drwxr-xr-x   4 root root    4096 Feb  2  2007 alchemist

1
@LIU Qingyuan 其次,这个 q 显示了接口中的多个故障。 1)-l 被设置为以晦涩的方式显示总数,几乎没有人需要。但是 -lh 是你 99.9% 的时间所需的。那么为什么不将 -l 设置为 MB,将 -lAlmostNeverNeeded 设置为块呢? 2)--help 中没有总数。 3)man 中没有总数。 4)让我们浪费时间:查看 --help,转到 man,记住 info,继续阅读。 (如果你在 Windows 上使用便携式 bash,则不包括 man 或 info,因此你需要像我现在正在做的那样搜索它。) 最后,在 SO 上:让我们惩罚本地人类问题。我们奖励对糟糕手册的无尽阅读。 - CoR
4个回答

107
您可以在所使用平台的ls文档中找到该行的定义。对于许多Linux系统中的coreutilsls,可以通过info coreutils ls找到相关信息:

对于每个列出的目录,在文件前加上一行“total BLOCKS”,其中BLOCKS是该目录中所有文件的总磁盘分配。


20
有趣的是,在我的系统上,man ls 并没有提到那行内容,但是 info coreutils ls 有。为什么 man lsinfo coreutils ls 对于同一个命令有不同的信息?为什么不把 ls 的文档只写一次呢?对于同一个命令拥有两个不同的文档看起来就像是引发问题的一种设置。 - HelloGoodbye
1
核心工具的“info”文档通常比“man”页面更详细。这就是为什么每个“man”页面末尾都有一个指向“info”部分获取更多详细信息的注释。 - Mat
8
啊,我执行了 info ls 命令,并且它产生了与 info coreutils ls 相同的输出。那么参数 coreutils 是干什么用的呢? - HelloGoodbye
@Mat 我已经修改了问题,希望它能够重新开放。希望你能投赞成票... - WinEunuuchs2Unix

50

公式:那个数字是什么?

int = 每个文件的(physical_blocks_in_use) * physical_block_size/ls_block_size)之和。

其中:

  • ls_block_size 是一个任意的环境变量(通常为512或1024字节),可以通过使用ls命令的--block-size=<int>标志、POSIXLY_CORRECT=1 GNU环境变量(以获取512字节单位)或-k标志来自由修改。
  • physical_block_size 是一个内部块接口的操作系统相关值,可能与底层硬件连接或不连接。该值通常为512b或1k,但完全取决于操作系统。它可以通过statfstat上的%B值来显示。 请注意,这个值(几乎总是)与现代存储设备上物理块的数量无关。

为什么这么令人困惑?

这个数字与任何物理或有意义的度量相当独立。许多初级程序员没有经验处理文件空洞硬链接/符号链接。此外,关于这个特定主题的可用文档几乎不存在。

"块大小"术语的不连贯性和模糊性是许多不同措施容易混淆以及围绕磁盘访问的相对深层次的抽象的结果。

冲突信息示例: du(或ls -s)与stat

在项目文件夹中运行du *将产生以下结果:(注意:ls -s返回相同的结果。)

dactyl:~/p% du *
2       check.cc
2       check.h
1       DONE
3       Makefile
3       memory.cc
5       memory.h
26      p2
4       p2.cc
2       stack.cc
14      stack.h

总计:2+2+1+3+3+5+26+4+2+14 = 62块

然而,当我们运行stat命令时,我们会看到一组不同的值。在同一目录下运行stat命令会得到如下结果:

dactyl:~/p% stat * --printf="%b\t(%B)\t%n: %s bytes\n"
3       (512)   check.cc: 221 bytes
3       (512)   check.h: 221 bytes
1       (512)   DONE: 0 bytes
5       (512)   Makefile: 980 bytes
6       (512)   memory.cc: 2069 bytes
10      (512)   memory.h: 4219 bytes
51      (512)   p2: 24884 bytes
8       (512)   p2.cc: 2586 bytes
3       (512)   stack.cc: 334 bytes
28      (512)   stack.h: 13028 bytes

总共: 3+3+1+5+6+10+51+8+3+28 = 118个块

注意: 您可以使用命令stat * --printf="%b\t(%B)\t%n: %s bytes\n"来输出(按顺序)块数,括号中的这些块的大小,文件名和字节大小,如上所示。

有两件重要的事情需要注意:

  • stat报告的是physical_blocks_in_usephysical_block_size,这些值是基于操作系统接口的。
  • du提供的是物理磁盘利用率的相当准确的估计。

参考一下,这是上面目录的ls -l

dactyl:~/p% ls -l
**total 59**
-rw-r--r--. 1 dhs217 grad   221 Oct 16  2013 check.cc
-rw-r--r--. 1 dhs217 grad   221 Oct 16  2013 check.h
-rw-r--r--. 1 dhs217 grad     0 Oct 16  2013 DONE
-rw-r--r--. 1 dhs217 grad   980 Oct 16  2013 Makefile
-rw-r--r--. 1 dhs217 grad  2069 Oct 16  2013 memory.cc
-rw-r--r--. 1 dhs217 grad  4219 Oct 16  2013 memory.h
-rwxr-xr-x. 1 dhs217 grad 24884 Oct 18  2013 p2
-rw-r--r--. 1 dhs217 grad  2586 Oct 16  2013 p2.cc
-rw-r--r--. 1 dhs217 grad   334 Oct 16  2013 stack.cc
-rw-r--r--. 1 dhs217 grad 13028 Oct 16  2013 stack.h

为什么我使用du命令得到不同的结果呢?在我的情况下,如果我使用du *,返回的总和是20 + 4 + 4 + 4 + 20 + 20 + 4 + 4 = 80,但是如果只运行du在同一个目录中,结果却是84? - undefined

28

这是列出的文件所使用的文件系统块总数,包括间接块。如果您在同一组文件上运行ls -s并将报告的数字相加,则会得到相同的数字。


这根本不是真的。例如:/bin/ls -s -> 总计 15 2 文件名 3 文件名2 3 文件名3 3 文件名4 2 文件名5 2 文件名6 2 文件名8 2 文件名9 - Don Scott
3
不知道你使用的是什么系统,但对我来说,这是真的。例如:https://gist.github.com/rfjakob/200f6001bf91cf801891 - Jakob
@Jakob发布了完整的答案,请看一下并告诉我是否搞清楚了。 - Don Scott
在 Git bash for Windows 中,这并不是真的。 - thdoan
1
我已经修改了问题,希望它能够重新开放。希望你能投赞成票... - WinEunuuchs2Unix

20

仅提一下 - 你可以使用-h(ls -lh)将其转换为人类可读格式。


不幸的是,它也将所有列出的行转换为人类可读格式。 - WinEunuuchs2Unix

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接