Tính kích thước thư mục bằng Python?


181

Trước khi tôi phát minh lại bánh xe đặc biệt này, có ai có thói quen tốt để tính kích thước của một thư mục bằng Python không? Sẽ rất tuyệt nếu thói quen sẽ định dạng kích thước độc đáo bằng Mb / Gb, v.v.


13
Nó sẽ không được tốt đẹp. Bạn nên có một hàm để tính kích thước và một hàm khá độc lập (chẳng hạn có thể được sử dụng với kích thước bộ nhớ) để "định dạng kích thước độc đáo theo Mb / Gb, v.v.".
John Machin

17
Có tôi biết nhưng điều này tiết kiệm hỏi hai câu hỏi.
Gary Willoughby

1
Các treelệnh trên hệ thống * nix làm tất cả những điều này miễn phí. tree -h -d --du /path/to/dir.
meh

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

Câu trả lời:


251

Điều này đi bộ tất cả các thư mục phụ; tổng kích thước tập tin:

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

Và một oneliner cho vui bằng cách sử dụng os.listdir ( Không bao gồm các thư mục con ):

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

Tài liệu tham khảo:

Đã cập nhật Để sử dụng os.path.getsize , điều này rõ ràng hơn so với sử dụng phương thức os.stat (). St_size.

Cảm ơn ghostdog74 đã chỉ ra điều này!

os.stat - st_size Cung cấp kích thước theo byte. Cũng có thể được sử dụng để có được kích thước tập tin và thông tin liên quan đến tập tin khác.

import os

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

Cập nhật 2018

Nếu bạn sử dụng Python 3.4 hoặc trước đó thì bạn có thể cân nhắc sử dụng walkphương pháp hiệu quả hơn được cung cấp bởi scandirgói bên thứ ba . Trong Python 3.5 trở lên, gói này đã được tích hợp vào thư viện chuẩn vàos.walk đã nhận được mức tăng hiệu suất tương ứng.

Cập nhật 2019

Gần đây tôi đã sử dụng pathlibngày càng nhiều, đây là một pathlibgiải pháp:

from pathlib import Path

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

14
1 nhưng oneliner không trả lại kết quả hợp lệ vì nó không phải là đệ quy
luc

2
Vâng, nó chỉ dành cho trường hợp thư mục phẳng.
monkut

35
Để giải trí thực sự, bạn có thể thực hiện kích thước đệ quy trong một dòng: sum (os.path.getsize (os.path.join (dirpath, tên tệp)) cho dirpath, dirnames, tên tệp trong os.walk (PATH) cho tên tệp trong tên tệp)
driax

2
Nhưng bạn phải sử dụng st_sizenếu bạn không muốn theo liên kết tượng trưng, ​​vì sau đó bạn nên sử dụng lstat.
asmeker 18/03 '

3
Cảnh báo! cái này không giống với 'du -sb'. Xem câu trả lời của Samuel Lampa! Mã của bạn bỏ qua kích thước của thư mục được sử dụng để lưu trữ FAT.
Yauhen Yakimovich

43

Một số phương pháp được đề xuất cho đến nay thực hiện đệ quy, một số khác sử dụng shell hoặc sẽ không tạo ra kết quả được định dạng gọn gàng. Khi mã của bạn là một lần cho các nền tảng Linux, bạn có thể nhận định dạng như bình thường, bao gồm đệ quy, dưới dạng một lớp. Ngoại trừ printdòng cuối cùng, nó sẽ hoạt động cho các phiên bản hiện tại python2python3:

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

là đơn giản, hiệu quả và sẽ làm việc cho các tệp và thư mục đa cấp:

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

13
Nb. Chỉ có Linux.
meawoppl

15
Python, là nền tảng chéo trong tự nhiên, có lẽ nên tránh xa điều này
Jonathan

11
Cảm ơn những nhận xét này. Tôi đã thêm một số cảnh báo về sự phụ thuộc nền tảng vào câu trả lời. Tuy nhiên, phần lớn mã Python nếu kịch bản một lần. Mã như vậy không được đi kèm với các giới hạn chức năng, các đoạn dài và dễ bị lỗi, hoặc kết quả không phổ biến trong các trường hợp cạnh, chỉ vì mục đích di động vượt quá bất kỳ nhu cầu nào . Như mọi khi, đó là một sự đánh đổi và trách nhiệm của nhà phát triển là phải lựa chọn một cách khôn ngoan;)
flaschbier

9
Nitpick: không phải Linux mà là Unix / Posix cụ thể :)
Mr Shark

3
Có lẽ nên thêm tùy chọn '-x' vào lệnh du để giới hạn tìm kiếm vào hệ thống tệp. Nói cách khác, sử dụng ['du', '-shx', path] để thay thế.
Keith Hanlan

24

Đây là một hàm đệ quy (nó đệ quy tổng kích thước của tất cả các thư mục con và các tệp tương ứng của chúng) trả về chính xác các byte giống như khi chạy "du -sb." trong linux (trong đó "." có nghĩa là "thư mục hiện tại"):

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
Hàm này cũng tính toán kích thước của symlink - nếu bạn muốn bỏ qua các liên kết tượng trưng, ​​bạn phải kiểm tra xem đó không phải là: if os.path.isfile (itempath) và os.path.islink (itempath) và elif os.path.itorir ( itempath) và os.path.islink (itempath).
sóng

17

Kích thước thư mục đệ quy Python 3.5 bằng cách sử dụng 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
Phương pháp Python 3 one-liner nếu không lo lắng về tính đệ quy sum([entry.stat().st_size for entry in os.scandir(file)]). Lưu ý đầu ra được tính bằng byte, / 1024 để nhận KB và / (1024 * 1024) để nhận MB.
weiji14

4
@ weiji14 Mất dấu ngoặc, nghĩa là , sum(entry.stat().st_size for entry in os.scandir(file)). Không có lý do để lập một danh sách, bởi vì cũng sumcó các vòng lặp.
Vedran Šego

8

câu trả lời monknut là tốt nhưng nó không thành công trên symlink bị hỏng, vì vậy bạn cũng phải kiểm tra xem đường dẫn này có thực sự tồn tại không

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

3
Bạn có thể không muốn theo liên kết tượng trưng. Bạn nên sử dụng lstat.
asmeker 18/03 '

8

Câu trả lời được chấp nhận không tính đến các liên kết cứng hoặc mềm và sẽ tính các tệp đó hai lần. Bạn muốn theo dõi những inodes nào bạn đã xem và không thêm kích thước cho các tệp đó.

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
Cân nhắc sử dụng os.lstat(chứ không phải os.stat), điều này tránh các liên kết tượng trưng sau: docs.python.org/2/l Library / os.html
Peter Briggs

7

Câu trả lời của Chris là tốt nhưng có thể được thực hiện nhiều hơn bằng cách sử dụng một bộ để kiểm tra các thư mục đã xem, điều này cũng tránh sử dụng một ngoại lệ cho luồng điều khiển:

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
Câu trả lời của Chris cũng không tính đến các liên kết tượng trưng cũng như kích thước của các thư mục. Tôi đã chỉnh sửa câu trả lời của bạn cho phù hợp, đầu ra của hàm cố định giờ giống hệt df -sb.
Creshal 11/12/13

7

một đệ quy lót:

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
Nó không phải là một lót mặc dù. Tuy nhiên, nó tính toán kích thước thư mục đệ quy (ngay cả khi thư mục có nhiều thư mục bên trong) theo byte và đưa ra giá trị chính xác.
Venkatesh

Tôi đã làm điều này dễ sử dụng và làm việc lần đầu tiên trên Windows
hum3

5

Đối với phần thứ hai của câu hỏi

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

Sử dụng pathlibtôi đã đưa ra một lớp lót này để có được kích thước của một thư mục:

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

Và đây là những gì tôi đã đưa ra cho một đầu ra được định dạng độc đáo:

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

Sử dụng:

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

Tôi cũng bắt gặp câu hỏi này , trong đó có một số chiến lược nhỏ gọn hơn và có thể hiệu quả hơn để in kích thước tệp.


4

Bạn có thể làm một cái gì đó như thế này:

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

trong trường hợp này tôi chưa kiểm tra kết quả trước khi trả lại, nếu bạn muốn, bạn có thể kiểm tra nó bằng lệnh.getstatusoutput.


Hiệu suất so với sử dụng os.walkđể kiểm tra kích thước thư mục con theo cách đệ quy như thế nào?
TomSawyer


4

Một chút muộn cho bữa tiệc nhưng trong một dòng với điều kiện bạn đã cài đặt global2nhân hóa . Lưu ý rằng trong Python 3, mặc định iglobcó chế độ đệ quy. Cách sửa đổi mã cho Python 3 là một bài tập nhỏ cho người đọc.

>>> 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
Bắt đầu với Python 3.5, tích hợp globhỗ trợ đệ quy. Bạn có thể sử dụng:glob.glob('/var/**', recursive=True)
adzenith

3

Kịch bản sau đây in kích thước thư mục của tất cả các thư mục con cho thư mục được chỉ định. Nó cũng cố gắng hưởng lợi (nếu có thể) từ việc lưu các cuộc gọi của các hàm đệ quy. Nếu một đối số bị bỏ qua, tập lệnh sẽ hoạt động trong thư mục hiện tại. Đầu ra được sắp xếp theo kích thước thư mục từ lớn nhất đến nhỏ nhất. Vì vậy, bạn có thể thích ứng nó cho nhu cầu của bạn.

PS tôi đã sử dụng công thức 578019 để hiển thị kích thước thư mục ở định dạng thân thiện với con người ( 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())

Đầu ra mẫu:

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: đã di chuyển null_decorator ở trên, như user2233949 khuyến nghị


Kịch bản của bạn hoạt động tốt, nhưng bạn cần di chuyển hàm null_decorator phía trên dòng 'if sys.version_info> = ...'. Nếu không, bạn sẽ nhận được 'null_decorator' không phải là ngoại lệ được xác định. Hoạt động tuyệt vời sau đó mặc dù.
dùng2233949

@ user2233949, cảm ơn bạn! Tôi đã sửa đổi mã tương ứng.
MaxU

3

sử dụng thư viện sh : mô-đun duthực hiện nó:

pip install sh

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

nếu bạn muốn vượt qua dấu sao, sử dụng globnhư được mô tả ở đây .

để chuyển đổi các giá trị trong phần đọc được của con người, hãy sử dụng humanize :

pip install humanize

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

2

để lấy kích thước của một tệp, có os.path.getsize ()

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

nó được báo cáo theo byte.


2

Đối với những gì nó có giá trị ... lệnh cây làm tất cả những điều này miễn phí:

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

Tôi yêu Python, nhưng cho đến nay, giải pháp đơn giản nhất cho vấn đề này không yêu cầu mã mới.


@ Abdur-RahmaanJanhangeer, đây là sự thật. Đây là sự thật.
meh

2

Nó rất tiện dụng:

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

Tôi đang sử dụng python 2.7.13 với scandir và đây là hàm đệ quy một lớp của tôi để lấy tổng kích thước của một thư mục:

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

Khi kích thước của các thư mục con được tính toán, nó sẽ cập nhật kích thước thư mục của cha mẹ và điều này sẽ tiếp tục cho đến khi đến được thư mục gốc.

Hàm sau sẽ tính kích thước của thư mục và tất cả các thư mục con của nó.

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

Nếu bạn đang ở trong HĐH Windows, bạn có thể làm:

cài đặt mô-đun pywin32 bằng cách khởi chạy:

Pip cài đặt pywin32

và sau đó mã hóa như sau:

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

Đây là một lớp lót thực hiện đệ quy (tùy chọn đệ quy có sẵn kể từ 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

cho python3.5 +

from pathlib import Path

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

0

Kịch bản lệnh này cho bạn biết tệp nào là lớn nhất trong CWD và cũng cho bạn biết tệp đó là thư mục nào. Kịch bản này hoạt động với tôi trên win8 và python 3.3.3 shell

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

Phải thừa nhận rằng đây là một loại tin tặc và chỉ hoạt động trên Unix / Linux.

Nó phù hợp du -sb .bởi vì trong thực tế, đây là một trình bao bọc bash Python chạy du -sb .lệnh.

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

Tôi hơi muộn (và mới) ở đây nhưng tôi đã chọn sử dụng mô đun quy trình con và dòng lệnh 'du' với Linux để lấy giá trị chính xác cho kích thước thư mục tính bằng MB. Tôi đã phải sử dụng if và elif cho thư mục gốc vì nếu không, quy trình con sẽ tăng lỗi do giá trị khác không được trả về.

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

Nhận kích thước thư mục

Tính chất của giải pháp:

  • trả về cả hai: kích thước biểu kiến ​​(số byte trong tệp) và dung lượng đĩa thực tế mà tệp sử dụng.
  • chỉ đếm các tệp được liên kết cứng một lần
  • đếm các liên kết theo cùng một cách du thực hiện
  • không sử dụng đệ quy
  • sử dụng st.st_blockscho không gian đĩa được sử dụng, do đó chỉ hoạt động trên các hệ thống giống Unix

Mật mã:

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)

Ví dụ sử dụng:

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

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

Kích thước tập tin con người có thể đọc được

Tính chất của giải pháp:

Mật mã:

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)

Ví dụ sử dụng:

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

0

Một giải pháp hoạt động trên Python 3.6 bằng pathlib.

from pathlib import Path

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

0

Python 3.6+ kích thước thư mục / tệp đệ quy bằng cách sử dụng os.scandir. Mạnh mẽ như trong câu trả lời của @blakev, nhưng ngắn hơn và theo kiểu trăn 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

Tôi đã viết hàm này cho tôi kích thước tổng thể chính xác của một thư mục, tôi đã thử các giải pháp vòng lặp khác với os.walk nhưng tôi không biết tại sao kết quả cuối cùng luôn nhỏ hơn kích thước thực tế (trên ub Ubuntu 18 env). Tôi phải làm điều gì đó sai nhưng ai quan tâm đã viết cái này hoạt động hoàn toàn tốt.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.