Menghitung ukuran direktori menggunakan Python?


182

Sebelum saya menemukan kembali roda khusus ini, adakah yang punya rutinitas yang bagus untuk menghitung ukuran direktori menggunakan Python? Akan sangat baik jika rutin akan memformat ukuran dengan baik dalam Mb / Gb dll.


13
TIDAK akan sangat menyenangkan. Anda harus memiliki satu fungsi untuk menghitung ukuran dan fungsi yang cukup independen (yang dapat digunakan juga dengan ukuran memori, misalnya) untuk "memformat ukuran dengan baik dalam Mb / Gb dll".
John Machin

17
Ya saya tahu tetapi ini menghemat dua pertanyaan.
Gary Willoughby

1
The treeperintah pada sistem nix * melakukan semua ini secara gratis. tree -h -d --du /path/to/dir.
meh

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

Jawaban:


252

Ini berjalan semua sub-direktori; menjumlahkan ukuran file:

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

Dan oneliner untuk bersenang-senang menggunakan os.listdir ( Tidak termasuk sub-direktori ):

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

Referensi:

Diperbarui Untuk menggunakan os.path.getsize , ini lebih jelas daripada menggunakan metode os.stat (). St_size.

Terima kasih kepada ghostdog74 untuk menunjukkan ini!

os.stat - st_size Memberikan ukuran dalam byte. Dapat juga digunakan untuk mendapatkan ukuran file dan informasi terkait file lainnya.

import os

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

Perbarui 2018

Jika Anda menggunakan Python 3.4 atau sebelumnya maka Anda dapat mempertimbangkan menggunakan metode yang lebih efisien walkyang disediakan oleh scandirpaket pihak ketiga . Dalam Python 3.5 dan yang lebih baru, paket ini telah dimasukkan ke dalam pustaka standar dan os.walktelah menerima peningkatan kinerja yang sesuai.

Perbarui 2019

Baru-baru ini saya semakin sering menggunakan pathlib, inilah pathlibsolusinya:

from pathlib import Path

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

14
1 tapi oneliner tidak kembali hasil yang valid karena tidak rekursif
luc

2
Ya, ini hanya untuk kasing direktori datar.
monkut

35
Untuk kesenangan nyata, Anda dapat melakukan ukuran rekursif dalam satu baris: jumlah (os.path.getsize (os.path.join (dirpath, nama file)) untuk dirpath, dirnames, nama file di os.walk (PATH) untuk nama file dalam nama file)
driax

2
Tetapi Anda harus menggunakan st_sizejika Anda ingin tidak mengikuti symlink, seperti yang seharusnya Anda gunakan lstat.
penanggung jawab

3
Peringatan! ini tidak sama dengan 'du -sb'. Lihat jawabannya oleh Samuel Lampa! Kode Anda mengabaikan ukuran folder yang digunakan untuk menyimpan FAT.
Yauhen Yakimovich

43

Beberapa pendekatan yang disarankan sejauh ini menerapkan rekursi, yang lain menggunakan cangkang atau tidak akan menghasilkan hasil yang diformat dengan rapi. Ketika kode Anda satu kali untuk platform Linux, Anda bisa memformat seperti biasa, termasuk rekursi, sebagai one-liner. Kecuali untuk printdi baris terakhir, ini akan berfungsi untuk versi python2dan 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('.'))

sederhana, efisien dan akan berfungsi untuk file dan direktori multilevel:

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

13
Nb. Hanya Linux.
meawoppl

15
Python, yang bersifat lintas platform, mungkin harus menghindarinya
Jonathan

11
Terima kasih atas komentar ini. Saya menambahkan beberapa peringatan tentang ketergantungan platform pada jawabannya. Namun, banyak kode Python jika skrip satu kali. Kode tersebut tidak boleh datang dengan keterbatasan fungsional, panjang dan rawan kesalahan bagian, atau hasil yang tidak biasa dalam kasus tepi, hanya demi portabilitas di luar kebutuhan apa pun . Ini, seperti biasa, merupakan pertukaran, dan merupakan tanggung jawab pengembang untuk memilih dengan bijak;)
flaschbier

9
Nitpick: bukan Linux tetapi khusus Unix / Posix :)
Mr Shark

3
Mungkin bijaksana untuk menambahkan opsi '-x' ke perintah du untuk membatasi pencarian ke sistem file. Dengan kata lain, gunakan ['du', '-shx', path] sebagai gantinya.
Keith Hanlan

24

Berikut adalah fungsi rekursif (ini secara rekursif merangkum ukuran semua subfolder dan file masing-masing) yang mengembalikan byte yang sama persis seperti ketika menjalankan "du -sb." di linux (di mana "." berarti "folder saat ini"):

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
Fungsi ini menghitung ukuran symlink juga - jika Anda ingin melewatkan symlink, Anda harus memeriksa bukan itu: jika os.path.isfile (itempath) dan os.path.islink (itempath) dan elif os.path.isdir ( itempath) dan os.path.islink (itempath).
airween

17

Python 3.5 menggunakan ukuran folder rekursif 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
Metode Python 3 one-liner jika tidak khawatir tentang rekursif-ness sum([entry.stat().st_size for entry in os.scandir(file)]). Catatan output dalam byte, / 1024 untuk mendapatkan KB dan / (1024 * 1024) untuk mendapatkan MB.
weiji14

4
@ weiji14 Menurunkan tanda kurung, yaitu sum(entry.stat().st_size for entry in os.scandir(file)),. Tidak ada alasan untuk membuat daftar, karena sumbutuh iterator juga.
Vedran Šego

8

Jawaban monknut baik tetapi gagal pada symlink rusak, jadi Anda juga harus memeriksa apakah jalur ini benar-benar ada

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

3
Anda mungkin tidak ingin mengikuti symlinks. Anda harus menggunakan lstat.
penanggung jawab

8

Jawaban yang diterima tidak memperhitungkan tautan keras atau lunak, dan akan menghitung file-file itu dua kali. Anda ingin melacak inode mana yang telah Anda lihat, dan tidak menambahkan ukuran untuk file-file itu.

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
Pertimbangkan untuk menggunakan os.lstat(daripada os.stat), yang menghindari tautan simbolis berikut: docs.python.org/2/library/os.html#os.lstat
Peter Briggs

7

Jawaban Chris baik tetapi bisa dibuat lebih idiomatis dengan menggunakan satu set untuk memeriksa direktori yang terlihat, yang juga menghindari menggunakan pengecualian untuk aliran kontrol:

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
Jawaban Chris juga tidak memperhitungkan symlink atau ukuran direktori itu sendiri. Saya telah mengedit jawaban Anda sesuai dengan itu, keluaran dari fungsi tetap sekarang identik dengan df -sb.
Creshal

7

satu liner rekursif:

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
Itu bukan satu liner sekalipun. Namun, ini menghitung ukuran folder secara rekursif (bahkan jika folder memiliki beberapa folder di dalamnya) dalam byte dan memberikan nilai yang benar.
Venkatesh

Saya memilih ini karena mudah digunakan dan bekerja pertama kali di Windows
hum3

5

Untuk bagian kedua dari pertanyaan

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

Menggunakan pathlibI muncul satu-liner ini untuk mendapatkan ukuran folder:

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

Dan inilah yang saya hasilkan untuk output yang diformat dengan baik:

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

Pemakaian:

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

Saya juga menemukan pertanyaan ini , yang memiliki beberapa strategi yang lebih kompak dan mungkin lebih banyak untuk mencetak ukuran file.


4

Anda dapat melakukan sesuatu seperti ini:

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

dalam hal ini saya belum menguji hasilnya sebelum mengembalikannya, jika mau, Anda dapat memeriksanya dengan commands.getstatusoutput.


bagaimana kinerja dibandingkan dengan digunakan os.walkuntuk memeriksa ukuran sub folder secara rekursif?
TomSawyer


4

Sedikit terlambat ke pesta tetapi dalam satu baris asalkan Anda memiliki glob2 dan memanusiakan diinstal. Perhatikan bahwa dalam Python 3, default iglobmemiliki mode rekursif. Cara memodifikasi kode untuk Python 3 dibiarkan sebagai latihan sepele bagi pembaca.

>>> 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
Dimulai dengan Python 3.5, built-in globmendukung rekursi. Anda dapat menggunakan:glob.glob('/var/**', recursive=True)
adzenith

3

Skrip berikut mencetak ukuran direktori dari semua sub-direktori untuk direktori yang ditentukan. Itu juga mencoba untuk mendapatkan keuntungan (jika mungkin) dari caching panggilan fungsi rekursif. Jika argumen dihilangkan, skrip akan berfungsi di direktori saat ini. Output diurutkan berdasarkan ukuran direktori dari yang terbesar ke yang terkecil. Jadi Anda bisa menyesuaikannya dengan kebutuhan Anda.

PS Saya sudah menggunakan resep 578019 untuk menunjukkan ukuran direktori dalam format ramah-manusia ( 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())

Output sampel:

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: pindah null_decorator di atas, seperti yang direkomendasikan user2233949


Skrip Anda berfungsi dengan baik, tetapi Anda harus memindahkan fungsi null_decorator di atas baris 'if sys.version_info> = ...'. Kalau tidak, Anda akan mendapatkan 'null_decorator' tidak termasuk pengecualian. Bekerja dengan baik setelah itu.
user2233949

@ user2233949, terima kasih! Saya mengubah kode sesuai.
Maks.

3

gunakan library sh : modul dumelakukannya:

pip install sh

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

jika Anda ingin melewati asterix, gunakan globseperti yang dijelaskan di sini .

untuk mengonversi nilai dalam yang dapat dibaca manusia, gunakan memanusiakan :

pip install humanize

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

2

untuk mendapatkan ukuran satu file, ada os.path.getsize ()

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

dilaporkan dalam byte.


2

Untuk apa nilainya ... perintah pohon melakukan semua ini secara gratis:

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

Saya suka Python, tetapi sejauh ini solusi paling sederhana untuk masalah ini tidak memerlukan kode baru.


@ Abdur-RahmaanJanhangeer, ini benar. Ini benar.
meh

2

Ini berguna:

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

Saya menggunakan python 2.7.13 dengan scandir dan inilah fungsi rekursif satu-liner saya untuk mendapatkan ukuran total folder:

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

Ketika ukuran sub-direktori dihitung, ia harus memperbarui ukuran folder induknya dan ini akan berlanjut hingga mencapai induk induk.

Fungsi berikut menghitung ukuran folder dan semua sub-foldernya.

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

Jika Anda berada di OS Windows yang dapat Anda lakukan:

instal modul pywin32 dengan meluncurkan:

pip instal pywin32

dan kemudian mengkode yang berikut ini:

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

Berikut ini adalah satu liner yang melakukannya secara rekursif (opsi rekursif tersedia pada Python 3.5):

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

untuk python3.5 +

from pathlib import Path

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

0

Script ini memberi tahu Anda file mana yang terbesar di CWD dan juga memberi tahu Anda di folder mana file tersebut berada. Skrip ini berfungsi untuk saya di shell win8 dan python 3.3.3

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

Harus diakui, ini jenis peretasan dan hanya berfungsi di Unix / Linux.

Ini cocok du -sb .karena pada dasarnya ini adalah pembungkus bash Python yang menjalankan du -sb .perintah.

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

Saya agak terlambat (dan baru) di sini, tetapi saya memilih untuk menggunakan modul subproses dan baris perintah 'du' dengan Linux untuk mengambil nilai yang akurat untuk ukuran folder dalam MB. Saya harus menggunakan if dan elif untuk folder root karena jika tidak subproses menimbulkan kesalahan karena nilai yang tidak nol dikembalikan.

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

Dapatkan ukuran direktori

Properti dari solusi:

  • mengembalikan keduanya: ukuran nyata (jumlah byte dalam file) dan ruang disk aktual yang digunakan file.
  • menghitung file yang ditautkan dengan keras hanya sekali
  • menghitung symlink dengan cara yang sama du tidak
  • tidak menggunakan rekursi
  • digunakan st.st_blocksuntuk ruang disk yang digunakan, sehingga hanya berfungsi pada sistem mirip Unix

Kode:

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)

Contoh penggunaan:

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

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

Ukuran file yang dapat dibaca manusia

Properti dari solusi:

Kode:

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)

Contoh penggunaan:

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

0

Solusi yang berfungsi pada Python 3.6 menggunakan pathlib.

from pathlib import Path

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

0

Python 3.6+ menggunakan ukuran folder / file rekursif os.scandir. Sekuat dalam jawaban oleh @blakev, tetapi lebih pendek dan dalam gaya python EAFP .

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

Saya menulis fungsi ini yang memberi saya ukuran keseluruhan yang akurat dari sebuah direktori, saya mencoba yang lain untuk solusi loop dengan os.walk tetapi saya tidak tahu mengapa hasil akhirnya selalu kurang dari ukuran sebenarnya (di ubuntu 18 env). Saya pasti telah melakukan sesuatu yang salah tetapi siapa yang peduli menulis ini berfungsi dengan baik.

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.