由于磁盘空间是按块分配的,因此以块与字节的形式报告目录所消耗的实际空间是否更准确?
如果大小为 1,025 字节的文件驻留在文件系统上,其中文件系统上的空间以 1,024 字节块为单位分配,则该文件会占用两个完整块。这似乎比说该文件占用 1,025 字节的空间更准确。
编辑:有问题的文件系统是 ext4,没有重复数据删除,没有压缩,fwiw。
这是我的尝试:
def getDirUsage(filepath, block_size=1024): # block_size as reported by os.statvfs()
'''
return the number of blocks consumed by a directory
'''
total_size = int(math.ceil(os.path.getsize(filepath)/block_size)) # debatable whether this should be included in the size
allfiles = os.listdir(filepath)
for f in allfiles:
p = os.path.join(filepath,f)
if os.path.isdir(p):
total_size += getDirUsage(p,block_size)
else:
total_size += int(math.ceil(os.stat(p).st_size/block_size))
return total_size
答案1
是的,块更好,因为它们是物理磁盘使用情况,但您需要以不同的方式获取它们
使用os.stat
字段st_blocks * 512
。https://docs.python.org/2/library/os.html#os.stat
os.stat(path)
stat()
在给定路径上 执行相当于系统调用的操作。 (此函数遵循符号链接;要统计符号链接,请使用lstat()
。)在某些 Unix 系统(例如 Linux)上,以下属性也可能可用:
st_blocks
- 为文件分配的 512 字节块数
st_blksize
- 用于高效文件系统 I/O 的文件系统块大小
通常,您最终会得到一个大小的倍数,st_blksize
除非您使用其中一个新的奇特的文件系统,该系统可以具有可变的块大小或重复数据删除。您希望文件系统上的重复数据删除可以通过文件系统实现来计算在块计数中,但考虑到这一点,重复数据删除有点像软/硬链接,但针对的是物理数据。也许 FS 可以将块划分为所有文件,或者只报告单个文件的块?可能不会。
您还需要考虑软/硬链接。目前,您将添加软链接目标的大小(尝试lstat
使用这些链接)。复制硬链接的一种简单方法是将块大小除以硬链接数量 ( st_nlink
),这样在整个驱动器中,您只需对 inode 计数一次,否则您必须跟踪 inode 数量。
除非你正在进行学习练习......正如 Ouki 提到的,就像du
其他人已经考虑过这个东西一样使用。
答案2
准确计算文件在磁盘上实际占用的空间并不简单,因为彻底的答案比仅将文件大小四舍五入到下一个磁盘块要复杂得多。
关于什么:
- 硬链接?
- 奇异的文件系统内部分配磁盘空间的方式(半块分配)?
- 压缩文件系统?
- 奇特的功能,例如“重复数据删除”?
如果你把所有这些加起来,如果没有对事物真正运作方式的正确内部了解,这项任务几乎是不可能的(所以绝对不是文件上的简单统计数据)。
系统工具
然而,有许多为此设计的系统工具,或者带有“占用块”选项。以下是最常用的 2 个:
杜
从男人
du
(来自 FreeBSD,更详细):DESCRIPTION The du utility displays the file system block usage for each file argument and for each directory in the file hierarchy rooted in each directory argument. If no file is specified, the block usage of the hierarchy rooted in the current directory is displayed.
LS-S
来自男人
ls
:-s, --size print the allocated size of each file, in blocks
(看起来
ls
“块”实际上是老式的1024字节块,而不是真正的磁盘块)
例子:
$ dumpe2fs /dev/mapper/vg_centurion-lv_root |head -20 |grep ^Block
dumpe2fs 1.41.12 (17-May-2010)
Block count: 13107200
Block size: 4096
所以我们的根文件系统有 4k 块。
$ ls -l
total 88
-rw-------. 1 root root 2510 Mar 20 18:00 anaconda-ks.cfg
-rw-r--r--. 1 root root 67834 Mar 20 17:59 install.log
-rw-r--r--. 1 root root 12006 Mar 20 17:57 install.log.syslog
与杜:
$ du -h anaconda-ks.cfg
4.0K anaconda-ks.cfg
和ls:
$ ls -ls
total 88
4 -rw-------. 1 root root 2510 Mar 20 18:00 anaconda-ks.cfg
72 -rw-r--r--. 1 root root 67834 Mar 20 17:59 install.log
12 -rw-r--r--. 1 root root 12006 Mar 20 17:57 install.log.syslog
答案3
并且不要忘记稀疏文件:
$ dd if=/dev/null of=MEAN_FILE bs=1024k seek=1024k
0+0 Datensätze ein
0+0 Datensätze aus
0 Bytes (0 B) kopiert, 1,0298e-05 s, 0,0 kB/s
$ ls -lh MEAN_FILE
-rw-r--r-- 1 yeti yeti 1,0T Apr 3 09:44 MEAN_FILE
$ du MEAN_FILE
0 MEAN_FILE