web-dev-qa-db-fra.com

Trouver la taille et l'espace libre du système de fichiers contenant un fichier donné

J'utilise Python 2.6 sous Linux. Quel est le moyen le plus rapide:

  • déterminer quelle partition contient un répertoire ou un fichier donné?

    Par exemple, supposons que /dev/sda2 est monté sur /home, et /dev/mapper/foo est monté sur /home/foo. De la chaîne "/home/foo/bar/baz" Je voudrais récupérer la paire ("/dev/mapper/foo", "home/foo").

  • et ensuite, pour obtenir des statistiques d'utilisation de la partition donnée? Par exemple, étant donné /dev/mapper/foo J'aimerais obtenir la taille de la partition et l'espace disponible (en octets ou environ en mégaoctets).

67

Si vous avez juste besoin de l'espace libre sur un périphérique, voir la réponse à l'aide de os.statvfs() ci-dessous.

Si vous avez également besoin du nom de périphérique et du point de montage associés au fichier, appelez un programme externe pour obtenir ces informations. df fournira toutes les informations dont vous avez besoin - lorsqu'il est appelé df filename _ imprime une ligne à propos de la partition contenant le fichier.

Pour donner un exemple:

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()

Notez que ceci est plutôt fragile, car cela dépend du format exact de la sortie df, mais je ne connais pas de solution plus robuste. (Il existe quelques solutions qui s'appuient sur le /proc systèmes de fichiers ci-dessous qui sont encore moins portables que celui-ci.)

43
Sven Marnach

Cela ne donne pas le nom de la partition, mais vous pouvez obtenir les statistiques du système de fichiers directement à l'aide de l'appel système statvfs Unix. Pour l'appeler depuis Python, utilisez os.statvfs('/home/foo/bar/baz') .

Les champs pertinents dans le résultat, selon 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.

Donc, pour donner un sens aux valeurs, multipliez par 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)
114
Mechanical snail
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

Quelques exemples de chemins sur mon ordinateur:

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

PS

si on Python ≥3.3, il y a shutil.disk_usage(path)) qui renvoie un tuple nommé de (total, used, free) exprimé en octets.

22
tzot

A partir de Python 3.3, il existe un moyen simple et direct de le faire avec la bibliothèque standard:

$ 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

Ces nombres sont en octets. Voir la documentation pour plus d'informations.

16
Xiong Chiamiov

Cela devrait faire tout ce que vous avez demandé:

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 __== '__main__':
    for part in disk_partitions():
        print part
        print "    %s\n" % str(disk_usage(part.mountpoint))

Le code ci-dessus est imprimé sur ma boîte:

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)
13
Giampaolo Rodolà

Le moyen le plus simple de le découvrir.

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)
8
mosquito

Pour le premier point, vous pouvez essayer d’utiliser os.path.realpath pour obtenir un chemin canonique, comparez-le avec /etc/mtab _ (Je suggèrerais même d'appeler getmntent, mais je ne trouve pas de moyen normal d'y accéder) pour trouver la correspondance la plus longue. (pour être sûr, vous devriez probablement stat le fichier et le point de montage présumé pour vérifier qu'ils sont bien sur le même périphérique)

Pour le deuxième point, utilisez os.statvfs pour obtenir des informations sur la taille et l’utilisation des blocs.

(Avertissement: je n'ai testé rien de tout cela, la plupart de ce que je sais provenait des sources de Coreutils)

6
Hasturkun

Pour la deuxième partie de votre question, "obtenir les statistiques d'utilisation de la partition donnée", psutil facilite la tâche avec la fonction disk_usage (path) . Étant donné un chemin, disk_usage() renvoie un tuple nommé comprenant l'espace total, utilisé et libre exprimé en octets, plus le pourcentage d'utilisation.

Exemple simple tiré de la documentation:

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

Psutil fonctionne avec Python versions de 2.6 à 3.6 et sous Linux, Windows et OSX, entre autres plates-formes.

4
andrew
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')
3
LawrenceLi

Généralement, le répertoire _/proc_ contient ces informations sous Linux, il s’agit d’un système de fichiers virtuel. Par exemple, _/proc/mounts_ donne des informations sur les disques montés en cours; et vous pouvez l'analyser directement. Des utilitaires comme top, df utilisent tous _/proc_.

Je ne l'ai pas utilisé, mais cela pourrait aussi aider, si vous voulez un wrapper: http://bitbucket.org/chrismiles/psi/wiki/Home

1
ustun