Python: os.stat (). St_size дает другое значение, чем du - PullRequest
7 голосов
/ 02 ноября 2010

Я создаю утилиту, которая будет проходить через каталоги, получать размеры дочерних каталогов и файлов для всех каталогов и сохранять их значение. Тем не менее, размеры не рассчитаны правильно.

Вот мой класс, который автоматически проходит через все подкаталоги:

class directory:
    '''
    Class that automatically traverses directories
    and builds a tree with size info
    '''
    def __init__(self, path, parent=None):

        if path[-1] != '/':
            # Add trailing /
            self.path = path + '/'
        else:
            self.path = path
        self.size = 4096
        self.parent = parent
        self.children = []
        self.errors = []
        for i in os.listdir(self.path):
            try:
                self.size += os.lstat(self.path + i).st_size
                if os.path.isdir(self.path + i) and not os.path.islink(self.path + i):
                    a = directory(self.path + i, self)
                    self.size += a.size
                    self.children.append(a)
            except OSError:
                self.errors.append(path + i)

У меня есть каталог видео, с которым я тестирую эту программу:

>>> a = directory('/var/media/television/The Wire')
>>> a.size
45289964053

Однако, когда я пытаюсь сделать то же самое с du, я получаю

$ du -sx /var/media/television/The\ Wire
44228824

В каталогах нет ссылок или чего-то особенного.

Может кто-нибудь объяснить, почему os.stat() дает странные показания размера?

Платформа:

  • Linux (Fedora 13)
  • Python 2.7

Ответы [ 4 ]

9 голосов
/ 02 ноября 2010

Рассмотрим этот файл foo

-rw-rw-r-- 1 unutbu unutbu 25334 2010-10-31 12:55 foo

Он состоит из 25334 байтов.

tune2fs сообщает, что foo находится в файловой системе с размером блока 4096 байт:

% sudo tune2fs -l /dev/mapper/vg1-OS1
...
Block size:               4096
...

Таким образом, самый маленький файл в файловой системе будет занимать 4096 байт, даже если его содержимое состоит всего из 1 байта. По мере увеличения файла пространство выделяется в блоках по 4096 байт.

du отчеты

% du -B1 foo
28672   foo

Обратите внимание, что 28672/4096 = 7. Это говорит о том, что foo занимает 7 4096-байтовых блоков в файловой системе. Это наименьшее количество блоков, необходимое для хранения 25334 байтов.

% du foo
28  foo

Эта версия du только что сообщила, что 28672/1024 округлено в меньшую сторону.

1 голос
/ 02 ноября 2010

du дает размер на диске по умолчанию, а не фактический размер файла, указанный в st_size.

$ du test.txt
    8    test.txt

$ du -b test.txt
    6095 test.txt


>>> os.stat('test.txt').st_size
6095
0 голосов
/ 02 ноября 2010

Я бы написал этот код как:

import os, os.path

def size_dir(d):
    file_walker = (
        os.path.join(root, f)
        for root, _, files in os.walk(d)
        for f in files
    )
    return sum(os.path.getsize(f) for f in file_walker)

Если вы хотите считать каталоги как 4k, то сделайте что-то вроде этого:

import os, os.path

def size_dir(d):
    file_walker = (
        os.path.join(root, f)
        for root, _, files in os.walk(d)
        for f in files
    )
    dir_walker = (
        4096
        for root, dirs, _ in os.walk(d)
        for d in dirs
    )
    return 4096 + sum(os.path.getsize(f) for f in file_walker) + sum(size for size in dir_walker)
0 голосов
/ 02 ноября 2010

В Linux (я использую CentOS), 'du -b' вернется в байтах и активирует --apparent-size , возвращая таким образом размер файла, а не количество дискового пространства использует. Попробуйте и посмотрите, соответствует ли это тому, что говорит Python os.stat.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...