查找包含给定文件的文件系统的大小和可用空间


76

我在Linux上使用Python 2.6。最快的方法是什么:

  • 确定哪个分区包含给定的目录或文件?

    例如,假设/dev/sda2已安装在/home/dev/mapper/foo/home/foo"/home/foo/bar/baz"我想从琴弦中取出那副("/dev/mapper/foo", "home/foo")

  • 然后,获取给定分区的使用情况统计信息?例如,给定/dev/mapper/foo我想要获取分区的大小和可用的可用空间(以字节为单位或大约以兆字节为单位)。


您是否考虑符号链接?尽管您可能拥有/ home和/ mnt / somedisk,但/ home / foo / x可能是目录/ mnt / somedisk / xyzzy的符号链接-因此它出现在/ home下,但实际上位于/ mnt / somedisk下
Piskvor离开了建于2010年

@Piskvor:不-暂时我不需要遵循符号链接,它们只是普通目录。第一个问题基本上是询问“查找最近的祖先目录,该目录上已安装了分区”。
Federico A. Ramponi 2010年

Answers:


49

如果您只需要设备上的可用空间,请参阅os.statvfs()下面的使用答案。

如果您还需要与文件关联的设备名称和安装点,则应调用外部程序以获取此信息。df将提供您需要的所有信息-调用时会在df filename包含文件的分区上打印一行。

举个例子:

import subprocess
df = subprocess.Popen(["df", "filename"], stdout=subprocess.PIPE)
output = df.communicate()[0]
device, size, used, available, percent, mountpoint = \
    output.split("\n")[1].split()

请注意,这相当脆弱,因为它取决于df输出的确切格式,但是我不知道更可靠的解决方案。(有一些解决方案依赖于/proc下面的文件系统,其可移植性甚至不如此解决方案。)


1
具体来说,他可以先执行导入命令,然后再执行commands.getoutput(“ df文件名| tail -1 | gawk'{print $ 6}'”)
jimbob博士10年

8
commands模块已被取代subprocess。当我可以使用Python进行输出分析时,我不会在bash中进行输出解析:)
Sven Marnach 2010年

4
我不知道df的“文件名”参数。将使用“ df -B MB文件名”。非常感谢。
Federico A. Ramponi 2010年

2
此方法并不总是有效。在我的环境中,输出消耗多于一行。在这种情况下,脚本将获取ValueError('need more than 5 values to unpack',因为设备列和其他信息位于不同的行中。
liuyix

4
@liuyix这个答案是针对Linux的,df特别是针对GNU coreutils的。如果不需要设备名称和安装点,请使用下一个答案中的代码。
Sven Marnach '16

124

这没有给出分区的名称,但是您可以使用statvfsUnix系统调用直接获取文件系统统计信息。要从Python调用它,请使用os.statvfs('/home/foo/bar/baz')

根据POSIX,结果中的相关字段:

unsigned long f_frsize   Fundamental file system block size. 
fsblkcnt_t    f_blocks   Total number of blocks on file system in units of f_frsize. 
fsblkcnt_t    f_bfree    Total number of free blocks. 
fsblkcnt_t    f_bavail   Number of free blocks available to 
                         non-privileged process.

因此,要理解这些值,请乘以f_frsize

import os
statvfs = os.statvfs('/home/foo/bar/baz')

statvfs.f_frsize * statvfs.f_blocks     # Size of filesystem in bytes
statvfs.f_frsize * statvfs.f_bfree      # Actual number of free bytes
statvfs.f_frsize * statvfs.f_bavail     # Number of free bytes that ordinary users
                                        # are allowed to use (excl. reserved space)

我只是在具有ubifs的嵌入式系统上遇到了这种失败。它提供了100MB的可用空间,其中只有10个可用。我不确定这100的来源。
Halfgaar

26

从Python 3.3开始,使用标准库可以轻松而直接地完成此操作:

$ cat free_space.py 
#!/usr/bin/env python3

import shutil

total, used, free = shutil.disk_usage(__file__)
print(total, used, free)

$ ./free_space.py 
1007870246912 460794834944 495854989312

这些数字以字节为单位。请参阅文档以获取更多信息。


24
import os

def get_mount_point(pathname):
    "Get the mount point of the filesystem containing pathname"
    pathname= os.path.normcase(os.path.realpath(pathname))
    parent_device= path_device= os.stat(pathname).st_dev
    while parent_device == path_device:
        mount_point= pathname
        pathname= os.path.dirname(pathname)
        if pathname == mount_point: break
        parent_device= os.stat(pathname).st_dev
    return mount_point

def get_mounted_device(pathname):
    "Get the device mounted at pathname"
    # uses "/proc/mounts"
    pathname= os.path.normcase(pathname) # might be unnecessary here
    try:
        with open("/proc/mounts", "r") as ifp:
            for line in ifp:
                fields= line.rstrip('\n').split()
                # note that line above assumes that
                # no mount points contain whitespace
                if fields[1] == pathname:
                    return fields[0]
    except EnvironmentError:
        pass
    return None # explicit

def get_fs_freespace(pathname):
    "Get the free space of the filesystem containing pathname"
    stat= os.statvfs(pathname)
    # use f_bfree for superuser, or f_bavail if filesystem
    # has reserved space for superuser
    return stat.f_bfree*stat.f_bsize

我的计算机上的一些示例路径名:

path 'trash':
  mp /home /dev/sda4
  free 6413754368
path 'smov':
  mp /mnt/S /dev/sde
  free 86761562112
path '/usr/local/lib':
  mp / rootfs
  free 2184364032
path '/proc/self/cmdline':
  mp /proc proc
  free 0

聚苯乙烯

如果在Python≥3.3上,则shutil.disk_usage(path)返回以(total, used, free)字节表示的命名元组。


如上所述,在具有ubifs的嵌入式系统上,使用statvfs的方法对我来说失败了。它提供了100MB的可用空间,其中只有10个可用。我不确定这100的来源。
Halfgaar

14

这应该使您所要求的一切:

import os
from collections import namedtuple

disk_ntuple = namedtuple('partition',  'device mountpoint fstype')
usage_ntuple = namedtuple('usage',  'total used free percent')

def disk_partitions(all=False):
    """Return all mountd partitions as a nameduple.
    If all == False return phyisical partitions only.
    """
    phydevs = []
    f = open("/proc/filesystems", "r")
    for line in f:
        if not line.startswith("nodev"):
            phydevs.append(line.strip())

    retlist = []
    f = open('/etc/mtab', "r")
    for line in f:
        if not all and line.startswith('none'):
            continue
        fields = line.split()
        device = fields[0]
        mountpoint = fields[1]
        fstype = fields[2]
        if not all and fstype not in phydevs:
            continue
        if device == 'none':
            device = ''
        ntuple = disk_ntuple(device, mountpoint, fstype)
        retlist.append(ntuple)
    return retlist

def disk_usage(path):
    """Return disk usage associated with path."""
    st = os.statvfs(path)
    free = (st.f_bavail * st.f_frsize)
    total = (st.f_blocks * st.f_frsize)
    used = (st.f_blocks - st.f_bfree) * st.f_frsize
    try:
        percent = ret = (float(used) / total) * 100
    except ZeroDivisionError:
        percent = 0
    # NB: the percentage is -5% than what shown by df due to
    # reserved blocks that we are currently not considering:
    # http://goo.gl/sWGbH
    return usage_ntuple(total, used, free, round(percent, 1))


if __name__ == '__main__':
    for part in disk_partitions():
        print part
        print "    %s\n" % str(disk_usage(part.mountpoint))

在我的盒子上,上面的代码打印:

giampaolo@ubuntu:~/dev$ python foo.py 
partition(device='/dev/sda3', mountpoint='/', fstype='ext4')
    usage(total=21378641920, used=4886749184, free=15405903872, percent=22.9)

partition(device='/dev/sda7', mountpoint='/home', fstype='ext4')
    usage(total=30227386368, used=12137168896, free=16554737664, percent=40.2)

partition(device='/dev/sdb1', mountpoint='/media/1CA0-065B', fstype='vfat')
    usage(total=7952400384, used=32768, free=7952367616, percent=0.0)

partition(device='/dev/sr0', mountpoint='/media/WB2PFRE_IT', fstype='iso9660')
    usage(total=695730176, used=695730176, free=0, percent=100.0)

partition(device='/dev/sda6', mountpoint='/media/Dati', fstype='fuseblk')
    usage(total=914217758720, used=614345637888, free=299872120832, percent=67.2)


次要nitpick-all是内置函数,不应用作函数中的变量。
亚当·马坦

可以用千兆字节表示吗?
Koustuv Chatterjee

9

找出它的最简单方法。

import os
from collections import namedtuple

DiskUsage = namedtuple('DiskUsage', 'total used free')

def disk_usage(path):
    """Return disk usage statistics about the given path.

    Will return the namedtuple with attributes: 'total', 'used' and 'free',
    which are the amount of total, used and free space, in bytes.
    """
    st = os.statvfs(path)
    free = st.f_bavail * st.f_frsize
    total = st.f_blocks * st.f_frsize
    used = (st.f_blocks - st.f_bfree) * st.f_frsize
    return DiskUsage(total, used, free)

使用=完全免费?
AK47

6

对于第一点,您可以尝试使用os.path.realpath来获得规范的路径,将其对照/etc/mtab(我实际上建议致电getmntent,但我找不到正常的访问方式)以找到最长的匹配项。(可以肯定的是,您可能应该stat同时使用文件和假定的挂载点,以验证它们是否确实在同一设备上)

第二点,用于os.statvfs获取块大小和使用情况信息。

(免责声明:我没有测试过,我所知道的大部分都来自coreutils来源)


重新起义:嗯,总是有的可能import ctypes; ctypes.cdll.LoadLibrary("libc.so.6").getmntent,但这并不是那么简单……
tzot 2010年

我很好奇为什么这会引起
反对

6

对于问题的第二部分,“获取给定分区的使用情况统计信息”,psutil通过disk_usage(path)函数使此操作变得容易。给定路径,disk_usage()将返回一个命名的元组,包括以字节为单位的总,已用和可用空间,以及使用率百分比。

文档中的简单示例:

>>> import psutil
>>> psutil.disk_usage('/')
sdiskusage(total=21378641920, used=4809781248, free=15482871808, percent=22.5)

Psutil可使用2.6至3.6的Python版本,以及Linux,Windows和OSX等平台。


4
import os

def disk_stat(path):
    disk = os.statvfs(path)
    percent = (disk.f_blocks - disk.f_bfree) * 100 / (disk.f_blocks -disk.f_bfree + disk.f_bavail) + 1
    return percent


print disk_stat('/')
print disk_stat('/data')

1
尽管此代码可以回答问题,但提供有关如何和/或为什么解决问题的其他上下文将提高​​答案的长期价值。
唐老鸭

disk_stat方法不带任何参数。但是,使用的想法os.statvfs很好。
suripoori

1

通常,/proc目录在Linux中包含此类信息,它是一个虚拟文件系统。例如,/proc/mounts提供有关当前已安装磁盘的信息;您可以直接解析它。公用事业喜欢topdf都让使用/proc

我没有使用过,但是如果您需要包装纸,这可能也有帮助:http : //bitbucket.org/chrismiles/psi/wiki/Home


0

可以按以下步骤检查Windows PC上的磁盘使用情况:

import psutil

fan = psutil.disk_usage(path="C:/")
print("Available: ", fan.total/1000000000)
print("Used: ", fan.used/1000000000)
print("Free: ", fan.free/1000000000)
print("Percentage Used: ", fan.percent, "%")
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.