Python kullanarak bir dizinin boyutunu mı hesaplıyorsunuz?


182

Bu tekerleği yeniden icat etmeden önce, Python kullanarak bir dizinin boyutunu hesaplamak için güzel bir rutin var mı? Rutin boyutu Mb / Gb vb. Olarak güzel biçimlendirirse çok güzel olurdu.


13
Çok hoş olmaz. Boyutu hesaplamak için bir işleve ve "boyutu Mb / Gb vb.
John Machin

17
Evet biliyorum ama bu iki soru sormaktan kurtarıyor.
Gary Willoughby

1
tree* Nix sistemlerde komut ücretsiz tüm bu yok. tree -h -d --du /path/to/dir.
meh

@mehdu -sh /path/to/dir/*
mrgloom

Yanıtlar:


253

Bu, tüm alt dizinlerde yürür; özet dosya boyutları:

import os

def get_size(start_path = '.'):
    total_size = 0
    for dirpath, dirnames, filenames in os.walk(start_path):
        for f in filenames:
            fp = os.path.join(dirpath, f)
            # skip if it is symbolic link
            if not os.path.islink(fp):
                total_size += os.path.getsize(fp)

    return total_size

print(get_size(), 'bytes')

Ve os.listdir kullanarak eğlenmek için bir oneliner ( Alt dizinleri içermez ):

import os
sum(os.path.getsize(f) for f in os.listdir('.') if os.path.isfile(f))

Referans:

Güncel kullanım için os.path.getsize bu os.stat (). St_size yöntem kullanarak daha nettir.

Bunu işaret ettiği için ghostdog74'e teşekkürler!

os.stat - st_size bayt cinsinden boyutunu verir. Dosya boyutu ve dosyayla ilgili diğer bilgileri almak için de kullanılabilir.

import os

nbytes = sum(d.stat().st_size for d in os.scandir('.') if d.is_file())

2018 Güncellemesi

Python 3.4 veya önceki bir sürümünü kullanıyorsanız walk, üçüncü taraf scandirpaketi tarafından sağlanan daha verimli yöntemi kullanmayı düşünebilirsiniz . Python 3.5 ve sonraki sürümlerde, bu paket standart kütüphaneye dahil edilmiştir ve os.walkperformansta buna karşılık gelen bir artış elde edilmiştir.

2019 Güncellemesi

Son zamanlarda pathlibdaha fazla kullanıyorum , işte bir pathlibçözüm:

from pathlib import Path

root_directory = Path('.')
sum(f.stat().st_size for f in root_directory.glob('**/*') if f.is_file())


14
+1 ancak oneliner, özyinelemediğinden geçerli bir sonuç döndürmüyor
luc

2
Evet, sadece düz dizin durumu için.
monkut

35
Gerçek eğlence için tek satırda yinelemeli bir boyut yapabilirsiniz: dosya adlarındaki dosya adı için oswalk (PATH) için toplam (os.path.getsize (os.path.join (dirpath, dosyaadı))
driax

2
Ancak st_size, sembolik bağlantıları takip etmek istemiyorsanız kullanmak zorundasınız lstat.
asmeurer

3
Uyarı! bu 'du -sb' ile aynı şey değildir. Samuel Lampa'nın cevabına bakın! Kodunuz FAT depolamak için kullanılan klasörün boyutunu yoksayar.
Yauhen Yakimovich

43

Şimdiye kadar önerilen yaklaşımlardan bazıları bir özyineleme uygular, diğerleri bir kabuk kullanır veya düzgün biçimlendirilmiş sonuçlar üretmez. Kodunuz Linux platformları için bir defalık olduğunda, her zamanki gibi biçimlendirmeyi alabilirsiniz, özyineleme dahil, tek katmanlı olarak. Hariç printson satırında, bu güncel sürümleri için çalışacak python2ve python3:

du.py
-----
#!/usr/bin/python3
import subprocess

def du(path):
    """disk usage in human readable format (e.g. '2,1GB')"""
    return subprocess.check_output(['du','-sh', path]).split()[0].decode('utf-8')

if __name__ == "__main__":
    print(du('.'))

basit, verimli ve dosyalar ve çok düzeyli dizinler için çalışacaktır:

$ chmod 750 du.py
$ ./du.py
2,9M

13
Nb. Yalnızca Linux.
meawoppl

15
Doğada çapraz platform olan Python muhtemelen bundan uzak durmalıdır
Jonathan

11
Bu açıklamalar için teşekkürler. Cevaba platform bağımlılığına ilişkin bir uyarı ekledim. Ancak, bir kerelik komut dosyası ise Python kodunun çoğu. Bu tür kodlar, herhangi bir ihtiyacın ötesinde bir taşınabilirlik uğruna, işlevsel sınırlamalar, uzun ve hataya açık pasajlar veya uç durumlarda nadir olmayan sonuçlar ile gelmemelidir . Her zamanki gibi bir değiş tokuş ve akıllıca seçim yapmak geliştiricinin sorumluluğundadır;)
flaschbier

9
Nitpick: Linux değil, Unix / Posix'e özel :)
Bay Shark

3
Aramayı dosya sistemine sınırlamak için du komutuna '-x' seçeneğini eklemek akıllıca olacaktır. Başka bir deyişle, onun yerine ['du', '-shx', yol] kullanın.
Keith Hanlan

24

Burada, "du -sb" komutunu çalıştırırken tam olarak aynı bayt döndüren özyinelemeli bir işlev (tüm alt klasörlerin ve ilgili dosyaların boyutunu özyinelemeli olarak özetler). linux'ta (burada ".", "geçerli klasör" anlamına gelir):

import os

def getFolderSize(folder):
    total_size = os.path.getsize(folder)
    for item in os.listdir(folder):
        itempath = os.path.join(folder, item)
        if os.path.isfile(itempath):
            total_size += os.path.getsize(itempath)
        elif os.path.isdir(itempath):
            total_size += getFolderSize(itempath)
    return total_size

print "Size: " + str(getFolderSize("."))

2
Bu işlev, sembolik bağlantının boyutunu da hesaplar - sembolik bağlantıları atlamak istiyorsanız, şunu kontrol etmeniz gerekir: eğer os.path.isfile (itempath) ve os.path.islink (itempath) ve elif os.path.isdir ( itempath) ve os.path.islink (itempath).
airween

17

Kullanarak Python 3.5 özyinelemeli klasör boyutu os.scandir

def folder_size(path='.'):
    total = 0
    for entry in os.scandir(path):
        if entry.is_file():
            total += entry.stat().st_size
        elif entry.is_dir():
            total += folder_size(entry.path)
    return total

1
Python 3 tek katmanlı yöntem özyinelemeden endişe etmiyorsa sum([entry.stat().st_size for entry in os.scandir(file)]). Not çıktısı bayt cinsindendir, KB almak için / 1024 ve MB almak için / (1024 * 1024).
weiji14

4
@ weiji14 Köşeli parantezleri kaybedin, yani sum(entry.stat().st_size for entry in os.scandir(file)). Liste yapmak için bir sebep yok, çünkü sumyineleyicileri de alıyor.
Vedran Šego

8

monknut cevabı iyi ama kırık symlink'te başarısız, bu yüzden bu yolun gerçekten var olup olmadığını da kontrol etmelisiniz

if os.path.exists(fp):
    total_size += os.stat(fp).st_size

3
Muhtemelen sembolik bağlantıları takip etmek istemezsiniz. Kullanmalısınız lstat.
asmeurer

8

Kabul edilen cevap, sabit veya yumuşak bağlantıları dikkate almaz ve bu dosyaları iki kez sayar. Hangi düğümleri gördüğünüzü takip etmek ve bu dosyaların boyutunu eklememek istersiniz.

import os
def get_size(start_path='.'):
    total_size = 0
    seen = {}
    for dirpath, dirnames, filenames in os.walk(start_path):
        for f in filenames:
            fp = os.path.join(dirpath, f)
            try:
                stat = os.stat(fp)
            except OSError:
                continue

            try:
                seen[stat.st_ino]
            except KeyError:
                seen[stat.st_ino] = True
            else:
                continue

            total_size += stat.st_size

    return total_size

print get_size()

5
Aşağıdaki sembolik bağlantılardan kaçınmak os.lstat(yerine os.stat) kullanmayı düşünün : docs.python.org/2/library/os.html#os.lstat
Peter Briggs

7

Chris'in cevabı iyi ama görülen dizinleri kontrol etmek için bir set kullanarak daha deyimsel hale getirilebilir, bu da kontrol akışı için bir istisna kullanmaktan kaçınır:

def directory_size(path):
    total_size = 0
    seen = set()

    for dirpath, dirnames, filenames in os.walk(path):
        for f in filenames:
            fp = os.path.join(dirpath, f)

            try:
                stat = os.stat(fp)
            except OSError:
                continue

            if stat.st_ino in seen:
                continue

            seen.add(stat.st_ino)

            total_size += stat.st_size

    return total_size  # size in bytes

2
Chris'in yanıtı, sembolik bağlantıları veya dizin boyutlarını da dikkate almaz. Cevabınızı buna göre düzenledim, sabit fonksiyonun çıktısı artık aynı df -sb.
Creshal

7

özyinelemeli bir astar:

def getFolderSize(p):
   from functools import partial
   prepend = partial(os.path.join, p)
   return sum([(os.path.getsize(f) if os.path.isfile(f) else getFolderSize(f)) for f in map(prepend, os.listdir(p))])

1
Yine de bir astar değil. Ancak, bayt cinsinden klasör boyutunu (klasör içinde birden çok klasör olsa bile) yinelemeli olarak hesaplar ve doğru değeri verir.
Venkatesh

Bunu kullanımı kolay olarak gittim ve Windows'ta ilk kez çalıştım
hum3

5

Sorunun ikinci kısmı için

def human(size):

    B = "B"
    KB = "KB" 
    MB = "MB"
    GB = "GB"
    TB = "TB"
    UNITS = [B, KB, MB, GB, TB]
    HUMANFMT = "%f %s"
    HUMANRADIX = 1024.

    for u in UNITS[:-1]:
        if size < HUMANRADIX : return HUMANFMT % (size, u)
        size /= HUMANRADIX

    return HUMANFMT % (size,  UNITS[-1])

5

Kullanarak pathlibbir klasör boyutu almak için bu tek astar geldi:

sum(file.stat().st_size for file in Path(folder).rglob('*'))

Ve güzel biçimlendirilmiş bir çıktı için buldum:

from pathlib import Path


def get_folder_size(folder):
    return ByteSize(sum(file.stat().st_size for file in Path(folder).rglob('*')))


class ByteSize(int):

    _kB = 1024
    _suffixes = 'B', 'kB', 'MB', 'GB', 'PB'

    def __new__(cls, *args, **kwargs):
        return super().__new__(cls, *args, **kwargs)

    def __init__(self, *args, **kwargs):
        self.bytes = self.B = int(self)
        self.kilobytes = self.kB = self / self._kB**1
        self.megabytes = self.MB = self / self._kB**2
        self.gigabytes = self.GB = self / self._kB**3
        self.petabytes = self.PB = self / self._kB**4
        *suffixes, last = self._suffixes
        suffix = next((
            suffix
            for suffix in suffixes
            if 1 < getattr(self, suffix) < self._kB
        ), last)
        self.readable = suffix, getattr(self, suffix)

        super().__init__()

    def __str__(self):
        return self.__format__('.2f')

    def __repr__(self):
        return '{}({})'.format(self.__class__.__name__, super().__repr__())

    def __format__(self, format_spec):
        suffix, val = self.readable
        return '{val:{fmt}} {suf}'.format(val=val, fmt=format_spec, suf=suffix)

    def __sub__(self, other):
        return self.__class__(super().__sub__(other))

    def __add__(self, other):
        return self.__class__(super().__add__(other))

    def __mul__(self, other):
        return self.__class__(super().__mul__(other))

    def __rsub__(self, other):
        return self.__class__(super().__sub__(other))

    def __radd__(self, other):
        return self.__class__(super().__add__(other))

    def __rmul__(self, other):
        return self.__class__(super().__rmul__(other))   

Kullanımı:

>>> size = get_folder_size("c:/users/tdavis/downloads")
>>> print(size)
5.81 GB
>>> size.GB
5.810891855508089
>>> size.gigabytes
5.810891855508089
>>> size.PB
0.005674699077644618
>>> size.MB
5950.353260040283
>>> size
ByteSize(6239397620)

Dosya boyutlarını yazdırmak için biraz daha kompakt ve muhtemelen daha performanslı stratejilere sahip olan bu soruya da rastladım .


4

Bunun gibi bir şey yapabilirsiniz:

import commands   
size = commands.getoutput('du -sh /path/').split()[0]

bu durumda sonucu döndürmeden önce test etmedim, isterseniz commands.getstatusoutput ile kontrol edebilirsiniz.


os.walkalt klasör boyutunu özyinelemeli olarak denetlemek için kullanılan performans nasıl ?
TomSawyer


4

Partiye biraz geç ama bir satırda glob2 ve insancıllaştırılmış olması koşuluyla . Python 3'te, varsayılanın iglobyinelemeli moda sahip olduğunu unutmayın. Python 3 için kod nasıl değiştirilir okuyucu için önemsiz bir egzersiz olarak bırakılır.

>>> import os
>>> from humanize import naturalsize
>>> from glob2 import iglob
>>> naturalsize(sum(os.path.getsize(x) for x in iglob('/var/**'))))
'546.2 MB'

1
Python 3.5 ile başlayarak, dahili globözyineleme özyinelemeyi destekler. glob.glob('/var/**', recursive=True)
Şunu

3

Aşağıdaki komut dosyası, belirtilen dizin için tüm alt dizinlerin dizin boyutunu yazdırır. Ayrıca, (eğer mümkünse), özyinelemeli işlevlerin çağrılarını önbelleğe almaktan faydalanmaya çalışır. Bir bağımsız değişken atlanırsa, komut dosyası geçerli dizinde çalışır. Çıktı, dizin boyutuna göre büyükten küçüğe doğru sıralanır. Böylece ihtiyaçlarınıza göre uyarlayabilirsiniz.

PS, dizin boyutunu insan dostu biçimde göstermek için 578019 tarifini kullandım ( http://code.activestate.com/recipes/578019/ )

from __future__ import print_function
import os
import sys
import operator

def null_decorator(ob):
    return ob

if sys.version_info >= (3,2,0):
    import functools
    my_cache_decorator = functools.lru_cache(maxsize=4096)
else:
    my_cache_decorator = null_decorator

start_dir = os.path.normpath(os.path.abspath(sys.argv[1])) if len(sys.argv) > 1 else '.'

@my_cache_decorator
def get_dir_size(start_path = '.'):
    total_size = 0
    if 'scandir' in dir(os):
        # using fast 'os.scandir' method (new in version 3.5)
        for entry in os.scandir(start_path):
            if entry.is_dir(follow_symlinks = False):
                total_size += get_dir_size(entry.path)
            elif entry.is_file(follow_symlinks = False):
                total_size += entry.stat().st_size
    else:
        # using slow, but compatible 'os.listdir' method
        for entry in os.listdir(start_path):
            full_path = os.path.abspath(os.path.join(start_path, entry))
            if os.path.isdir(full_path):
                total_size += get_dir_size(full_path)
            elif os.path.isfile(full_path):
                total_size += os.path.getsize(full_path)
    return total_size

def get_dir_size_walk(start_path = '.'):
    total_size = 0
    for dirpath, dirnames, filenames in os.walk(start_path):
        for f in filenames:
            fp = os.path.join(dirpath, f)
            total_size += os.path.getsize(fp)
    return total_size

def bytes2human(n, format='%(value).0f%(symbol)s', symbols='customary'):
    """
    (c) http://code.activestate.com/recipes/578019/

    Convert n bytes into a human readable string based on format.
    symbols can be either "customary", "customary_ext", "iec" or "iec_ext",
    see: http://goo.gl/kTQMs

      >>> bytes2human(0)
      '0.0 B'
      >>> bytes2human(0.9)
      '0.0 B'
      >>> bytes2human(1)
      '1.0 B'
      >>> bytes2human(1.9)
      '1.0 B'
      >>> bytes2human(1024)
      '1.0 K'
      >>> bytes2human(1048576)
      '1.0 M'
      >>> bytes2human(1099511627776127398123789121)
      '909.5 Y'

      >>> bytes2human(9856, symbols="customary")
      '9.6 K'
      >>> bytes2human(9856, symbols="customary_ext")
      '9.6 kilo'
      >>> bytes2human(9856, symbols="iec")
      '9.6 Ki'
      >>> bytes2human(9856, symbols="iec_ext")
      '9.6 kibi'

      >>> bytes2human(10000, "%(value).1f %(symbol)s/sec")
      '9.8 K/sec'

      >>> # precision can be adjusted by playing with %f operator
      >>> bytes2human(10000, format="%(value).5f %(symbol)s")
      '9.76562 K'
    """
    SYMBOLS = {
        'customary'     : ('B', 'K', 'M', 'G', 'T', 'P', 'E', 'Z', 'Y'),
        'customary_ext' : ('byte', 'kilo', 'mega', 'giga', 'tera', 'peta', 'exa',
                           'zetta', 'iotta'),
        'iec'           : ('Bi', 'Ki', 'Mi', 'Gi', 'Ti', 'Pi', 'Ei', 'Zi', 'Yi'),
        'iec_ext'       : ('byte', 'kibi', 'mebi', 'gibi', 'tebi', 'pebi', 'exbi',
                           'zebi', 'yobi'),
    }
    n = int(n)
    if n < 0:
        raise ValueError("n < 0")
    symbols = SYMBOLS[symbols]
    prefix = {}
    for i, s in enumerate(symbols[1:]):
        prefix[s] = 1 << (i+1)*10
    for symbol in reversed(symbols[1:]):
        if n >= prefix[symbol]:
            value = float(n) / prefix[symbol]
            return format % locals()
    return format % dict(symbol=symbols[0], value=n)

############################################################
###
###  main ()
###
############################################################
if __name__ == '__main__':
    dir_tree = {}
    ### version, that uses 'slow' [os.walk method]
    #get_size = get_dir_size_walk
    ### this recursive version can benefit from caching the function calls (functools.lru_cache)
    get_size = get_dir_size

    for root, dirs, files in os.walk(start_dir):
        for d in dirs:
            dir_path = os.path.join(root, d)
            if os.path.isdir(dir_path):
                dir_tree[dir_path] = get_size(dir_path)

    for d, size in sorted(dir_tree.items(), key=operator.itemgetter(1), reverse=True):
        print('%s\t%s' %(bytes2human(size, format='%(value).2f%(symbol)s'), d))

    print('-' * 80)
    if sys.version_info >= (3,2,0):
        print(get_dir_size.cache_info())

Örnek çıktı:

37.61M  .\subdir_b
2.18M   .\subdir_a
2.17M   .\subdir_a\subdir_a_2
4.41K   .\subdir_a\subdir_a_1
----------------------------------------------------------
CacheInfo(hits=2, misses=4, maxsize=4096, currsize=4)

EDIT: n22_decorator'ı yukarıdaki 2222949'un önerdiği gibi taşıdı


Komut dosyanız iyi çalışıyor, ancak null_decorator işlevini 'if sys.version_info> = ...' satırının üstüne taşımanız gerekiyor. Aksi takdirde 'null_decorator' tanımlı bir istisna alırsınız. Bundan sonra harika çalışıyor.
user2233949

@ user2233949, teşekkür ederim! Kodu buna göre değiştirdim.
MaxU

3

kitaplığı kullan sh : modül dubunu yapar:

pip install sh

import sh
print( sh.du("-s", ".") )
91154728        .

asterix'i geçmek istiyorsanız, buradaglob açıklandığı gibi kullanın .

okunabilir değerlerdeki değerleri dönüştürmek için humanize komutunu kullanın :

pip install humanize

import humanize
print( humanize.naturalsize( 91157384 ) )
91.2 MB

2

bir dosyanın boyutunu almak için os.path.getsize () var

>>> import os
>>> os.path.getsize("/path/file")
35L

bayt cinsinden bildirilir.


2

Değer için ... ağaç komutu tüm bunları ücretsiz olarak yapar:

tree -h --du /path/to/dir  # files and dirs
tree -h -d --du /path/to/dir  # dirs only

Python seviyorum, ama bugüne kadar sorunun en basit çözümü yeni bir kod gerektirmez.


@ Abdur-RahmaanJanhangeer, bu doğru. Bu doğru.
meh

2

Kullanışlı:

import os
import stat

size = 0
path_ = ""
def calculate(path=os.environ["SYSTEMROOT"]):
    global size, path_
    size = 0
    path_ = path

    for x, y, z in os.walk(path):
        for i in z:
            size += os.path.getsize(x + os.sep + i)

def cevir(x):
    global path_
    print(path_, x, "Byte")
    print(path_, x/1024, "Kilobyte")
    print(path_, x/1048576, "Megabyte")
    print(path_, x/1073741824, "Gigabyte")

calculate("C:\Users\Jundullah\Desktop")
cevir(size)

Output:
C:\Users\Jundullah\Desktop 87874712211 Byte
C:\Users\Jundullah\Desktop 85815148.64355469 Kilobyte
C:\Users\Jundullah\Desktop 83803.85609722137 Megabyte
C:\Users\Jundullah\Desktop 81.83970321994275 Gigabyte

1

Scandir ile python 2.7.13 kullanıyorum ve işte bir klasörün toplam boyutunu elde etmek için benim tek katmanlı özyinelemeli işlev:

from scandir import scandir
def getTotFldrSize(path):
    return sum([s.stat(follow_symlinks=False).st_size for s in scandir(path) if s.is_file(follow_symlinks=False)]) + \
    + sum([getTotFldrSize(s.path) for s in scandir(path) if s.is_dir(follow_symlinks=False)])

>>> print getTotFldrSize('.')
1203245680

https://pypi.python.org/pypi/scandir


1

Alt dizinlerin boyutu hesaplandığında, üst klasörünün klasör boyutunu güncellemelidir ve bu kök üst öğeye ulaşana kadar devam eder.

Aşağıdaki işlev, klasörün ve tüm alt klasörlerinin boyutunu hesaplar.

import os

def folder_size(path):
    parent = {}  # path to parent path mapper
    folder_size = {}  # storing the size of directories
    folder = os.path.realpath(path)

    for root, _, filenames in os.walk(folder):
        if root == folder:
            parent[root] = -1  # the root folder will not have any parent
            folder_size[root] = 0.0  # intializing the size to 0

        elif root not in parent:
            immediate_parent_path = os.path.dirname(root)  # extract the immediate parent of the subdirectory
            parent[root] = immediate_parent_path  # store the parent of the subdirectory
            folder_size[root] = 0.0  # initialize the size to 0

        total_size = 0
        for filename in filenames:
            filepath = os.path.join(root, filename)
            total_size += os.stat(filepath).st_size  # computing the size of the files under the directory
        folder_size[root] = total_size  # store the updated size

        temp_path = root  # for subdirectories, we need to update the size of the parent till the root parent
        while parent[temp_path] != -1:
            folder_size[parent[temp_path]] += total_size
            temp_path = parent[temp_path]

    return folder_size[folder]/1000000.0

1

Windows işletim sistemindeyseniz şunları yapabilirsiniz:

pywin32 modülünü başlatarak kurun:

pip kurulum pywin32

ve sonra aşağıdakileri kodlar:

import win32com.client as com

def get_folder_size(path):
   try:
       fso = com.Dispatch("Scripting.FileSystemObject")
       folder = fso.GetFolder(path)
       size = str(round(folder.Size / 1048576))
       print("Size: " + size + " MB")
   except Exception as e:
       print("Error --> " + str(e))

1

İşte özyinelemeli yapan bir astar (Python 3.5'ten itibaren özyinelemeli seçenek mevcuttur):

import os
import glob
print(sum(os.path.getsize(f) for f in glob.glob('**', recursive=True) if os.path.isfile(f))/(1024*1024))

1

python3.5 + için

from pathlib import Path

def get_size(path):
    return sum(p.stat().st_size for p in Path(path).rglob('*'))

0

Bu komut dosyası CWD'deki en büyük dosyanın hangisi olduğunu ve dosyanın hangi klasörde olduğunu belirtir. Bu script benim için win8 ve python 3.3.3 kabuğunda çalışıyor

import os

folder=os.cwd()

number=0
string=""

for root, dirs, files in os.walk(folder):
    for file in files:
        pathname=os.path.join(root,file)
##        print (pathname)
##        print (os.path.getsize(pathname)/1024/1024)
        if number < os.path.getsize(pathname):
            number = os.path.getsize(pathname)
            string=pathname


##        print ()


print (string)
print ()
print (number)
print ("Number in bytes")

0

Kuşkusuz, bu bir tür hackish ve sadece Unix / Linux üzerinde çalışıyor.

Eşleşir du -sb .çünkü gerçekte bu du -sb .komutu çalıştıran bir Python bash sarmalayıcısıdır .

import subprocess

def system_command(cmd):
    """"Function executes cmd parameter as a bash command."""
    p = subprocess.Popen(cmd,
                         stdout=subprocess.PIPE,
                         stderr=subprocess.PIPE,
                         shell=True)
    stdout, stderr = p.communicate()
    return stdout, stderr

size = int(system_command('du -sb . ')[0].split()[0])

0

Burada biraz geç kaldım (ve yeniyim) ama alt işlem modülünü ve 'du' komut satırını Linux ile kullanmayı seçtim. Kök klasör için if ve elif kullanmak zorunda kaldım çünkü aksi takdirde alt süreç sıfır olmayan değer nedeniyle hata verir.

import subprocess
import os

#
# get folder size
#
def get_size(self, path):
    if os.path.exists(path) and path != '/':
        cmd = str(subprocess.check_output(['sudo', 'du', '-s', path])).\
            replace('b\'', '').replace('\'', '').split('\\t')[0]
        return float(cmd) / 1000000
    elif os.path.exists(path) and path == '/':
        cmd = str(subprocess.getoutput(['sudo du -s /'])). \
            replace('b\'', '').replace('\'', '').split('\n')
        val = cmd[len(cmd) - 1].replace('/', '').replace(' ', '')
        return float(val) / 1000000
    else: raise ValueError

0

Dizin boyutunu al

Çözümün özellikleri:

  • her ikisini de döndürür: görünür boyut (dosyadaki bayt sayısı) ve dosyaların kullandığı gerçek disk alanı.
  • sabit bağlantılı dosyaları yalnızca bir kez sayar
  • Sayımlar sembolik bağların aynı şekilde duyapar
  • özyineleme kullanmaz
  • kullanılan st.st_blocksdisk alanı için kullanır , bu nedenle yalnızca Unix benzeri sistemlerde çalışır

Kod:

import os


def du(path):
    if os.path.islink(path):
        return (os.lstat(path).st_size, 0)
    if os.path.isfile(path):
        st = os.lstat(path)
        return (st.st_size, st.st_blocks * 512)
    apparent_total_bytes = 0
    total_bytes = 0
    have = []
    for dirpath, dirnames, filenames in os.walk(path):
        apparent_total_bytes += os.lstat(dirpath).st_size
        total_bytes += os.lstat(dirpath).st_blocks * 512
        for f in filenames:
            fp = os.path.join(dirpath, f)
            if os.path.islink(fp):
                apparent_total_bytes += os.lstat(fp).st_size
                continue
            st = os.lstat(fp)
            if st.st_ino in have:
                continue  # skip hardlinks which were already counted
            have.append(st.st_ino)
            apparent_total_bytes += st.st_size
            total_bytes += st.st_blocks * 512
        for d in dirnames:
            dp = os.path.join(dirpath, d)
            if os.path.islink(dp):
                apparent_total_bytes += os.lstat(dp).st_size
    return (apparent_total_bytes, total_bytes)

Örnek kullanım:

>>> du('/lib')
(236425839, 244363264)

$ du -sb /lib
236425839   /lib
$ du -sB1 /lib
244363264   /lib

İnsan tarafından okunabilir dosya boyutu

Çözümün özellikleri:

Kod:

def humanized_size(num, suffix='B', si=False):
    if si:
        units = ['','K','M','G','T','P','E','Z']
        last_unit = 'Y'
        div = 1000.0
    else:
        units = ['','Ki','Mi','Gi','Ti','Pi','Ei','Zi']
        last_unit = 'Yi'
        div = 1024.0
    for unit in units:
        if abs(num) < div:
            return "%3.1f%s%s" % (num, unit, suffix)
        num /= div
    return "%.1f%s%s" % (num, last_unit, suffix)

Örnek kullanım:

>>> humanized_size(236425839)
'225.5MiB'
>>> humanized_size(236425839, si=True)
'236.4MB'
>>> humanized_size(236425839, si=True, suffix='')
'236.4M'

0

Pathlib kullanarak Python 3.6 üzerinde çalışan bir çözüm.

from pathlib import Path

sum([f.stat().st_size for f in Path("path").glob("**/*")])

0

Python 3.6+ özyinelemeli klasör / dosya boyutu kullanarak os.scandir. @Blakev'in yanıtı kadar güçlü , ancak daha kısa ve EAFP python tarzında .

import os

def size(path, *, follow_symlinks=False):
    try:
        with os.scandir(path) as it:
            return sum(size(entry, follow_symlinks=follow_symlinks) for entry in it)
    except NotADirectoryError:
        return os.stat(path, follow_symlinks=follow_symlinks).st_size

0
def recursive_dir_size(path):
    size = 0

    for x in os.listdir(path):
        if not os.path.isdir(os.path.join(path,x)):
            size += os.stat(os.path.join(path,x)).st_size
        else:
            size += recursive_dir_size(os.path.join(path,x))

    return size

Bana bir dizinin doğru genel boyutunu veren bu işlevi yazdı, os.walk ile döngü çözümleri için diğer denedim ama neden sonuç her zaman gerçek boyuttan daha az olduğunu bilmiyorum (ubuntu 18 env). Yanlış bir şey yapmış olmalıydım ama kimin umurunda ki bu mükemmel çalışıyor.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.