คำนวณขนาดของไดเรกทอรีด้วย Python หรือไม่?


182

ก่อนที่ฉันจะสร้างวงล้อนี้ขึ้นมาใหม่ใครมีรูทีนที่ดีสำหรับการคำนวณขนาดของไดเรกทอรีโดยใช้ Python หรือไม่? มันจะดีมากถ้ารูทีนจะจัดรูปแบบขนาดเป็น Mb / Gb เป็นต้น


13
มันจะไม่ดีมาก คุณควรมีฟังก์ชั่นหนึ่งในการคำนวณขนาดและฟังก์ชั่นที่ค่อนข้างอิสระ (ซึ่งสามารถใช้กับขนาดหน่วยความจำได้เช่นกัน) เพื่อ "จัดรูปแบบขนาดได้เป็น Mb / Gb ฯลฯ "
John Machin

17
ใช่ฉันรู้ แต่นี่ช่วยให้ถามคำถามสองข้อ
Gary Willoughby

1
treeคำสั่งบนระบบระวัง * ไม่ทั้งหมดนี้ฟรี tree -h -d --du /path/to/dir.
Meh

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

คำตอบ:


252

สิ่งนี้จะเดินไดเรกทอรีย่อยทั้งหมด ข้อสรุปขนาดไฟล์:

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

และ oneliner เพื่อความสนุกสนานโดยใช้os.listdir ( ไม่รวมไดเรกทอรีย่อย ):

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

อ้างอิง:

อัปเดต เมื่อต้องการใช้os.path.getsizeนี่จะชัดเจนกว่าการใช้วิธี os.stat (). st_size

ขอบคุณ ghostdog74 ที่ชี้เรื่องนี้ออกมา!

os.stat - st_sizeให้ขนาดเป็นไบต์ สามารถใช้เพื่อรับขนาดไฟล์และข้อมูลอื่น ๆ ที่เกี่ยวข้องกับไฟล์

import os

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

อัปเดต 2018

หากคุณใช้ Python 3.4 หรือเก่ากว่าคุณอาจพิจารณาใช้walkวิธีที่มีประสิทธิภาพมากขึ้นจากscandirแพ็คเกจของบุคคลที่สาม ใน Python 3.5 และใหม่กว่าแพ็คเกจนี้ได้ถูกรวมเข้ากับไลบรารีมาตรฐานและos.walkได้รับการเพิ่มประสิทธิภาพที่สอดคล้องกัน

อัปเดต 2019

เมื่อเร็ว ๆ นี้ฉันได้ใช้pathlibมากขึ้นต่อไปนี้เป็นpathlibวิธีแก้ปัญหา:

from pathlib import Path

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


14
+1 แต่ผู้เผยแพร่รายเดียวไม่ส่งคืนผลลัพธ์ที่ถูกต้องเพราะไม่ใช่การเรียกซ้ำ
luc

2
ใช่มันเป็นเพียงกรณีไดเรกทอรีแบน
monkut

35
เพื่อความสนุกที่แท้จริงคุณสามารถทำซ้ำขนาดในหนึ่งบรรทัด: sum (os.path.getsize (os.path.join (dirpath, filename)) สำหรับ dirpath, dirnames, ชื่อไฟล์ใน os.walk (PATH) สำหรับชื่อไฟล์ในชื่อไฟล์)
driax

2
แต่คุณต้องใช้st_sizeถ้าคุณต้องการที่จะไม่ปฏิบัติตาม symlinks lstatที่คุณควรใช้แล้ว
asmeurer

3
คำเตือน! สิ่งนี้ไม่เหมือนกับ 'du -sb' ดูคำตอบของ Samuel Lampa! รหัสของคุณจะไม่สนใจขนาดของโฟลเดอร์ที่ใช้ในการจัดเก็บ FAT
Yauhen Yakimovich

43

แนวทางบางอย่างที่แนะนำให้ใช้การเรียกซ้ำจนถึงขณะนี้บางวิธีใช้เชลล์หรือจะไม่ให้ผลลัพธ์ที่จัดรูปแบบเรียบร้อย เมื่อรหัสของคุณใช้ครั้งเดียวสำหรับแพลตฟอร์ม Linux คุณสามารถรับการจัดรูปแบบตามปกติรวมถึงการเรียกซ้ำเป็นแบบครั้งเดียว ยกเว้นprintในบรรทัดสุดท้ายมันจะทำงานกับเวอร์ชันปัจจุบันของpython2และ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('.'))

นั้นง่ายมีประสิทธิภาพและจะทำงานกับไฟล์และไดเรกทอรีหลายระดับ:

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

13
nb Linux เท่านั้น
meawoppl

15
Python ซึ่งเป็นแพลตฟอร์มข้ามธรรมชาติอาจจะไม่ควรพลาดสิ่งนี้
Jonathan

11
ขอบคุณสำหรับข้อสังเกตเหล่านี้ ฉันได้เพิ่มข้อแม้บางประการเกี่ยวกับการพึ่งพาแพลตฟอร์มกับคำตอบ อย่างไรก็ตามรหัส Python ส่วนใหญ่หากใช้สคริปต์เพียงครั้งเดียว รหัสดังกล่าวไม่ควรมาพร้อมกับข้อ จำกัด การทำงานทางเดินยาวและผิดพลาดได้ง่ายหรือผลเรื่องผิดปกติในกรณีขอบเพียงเพื่อประโยชน์ในการพกพาที่เกินความจำเป็นใดเป็นเช่นเคยการแลกเปลี่ยนและมันอยู่ในความรับผิดชอบของนักพัฒนาที่จะเลือกอย่างชาญฉลาด;)
flaschbier

9
Nitpick: ไม่ใช่ Linux แต่เฉพาะ Unix / Posix :)
Mr Shark

3
อาจเป็นการดีที่จะเพิ่มตัวเลือก '-x' ลงในคำสั่ง du เพื่อ จำกัด การค้นหาในระบบไฟล์ กล่าวอีกนัยหนึ่งให้ใช้ ['du', '-shx', path] แทน
Keith Hanlan

24

นี่คือฟังก์ชั่นวนซ้ำ (โดยรวมจำนวนซ้ำของโฟลเดอร์ย่อยทั้งหมดและไฟล์ตามลำดับ) ซึ่งจะส่งกลับไบต์เดียวกันทุกครั้งที่เรียกใช้ "du -sb" ใน linux (โดยที่ "." หมายถึง "โฟลเดอร์ปัจจุบัน"):

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
ฟังก์ชั่นนี้จะคำนวณขนาดของ symlink ด้วย - หากคุณต้องการข้าม symlink คุณต้องตรวจสอบว่าไม่ใช่: if os.path.isfile (itempath) และ os.path.islink (itempath) และ elif os.path.isdir ( itempath) และ os.path.islink (itempath)
airween

17

Python 3.5 ใช้ขนาดโฟลเดอร์แบบเรียกซ้ำ 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
งูหลาม 3 วิธีหนึ่งซับหากไม่ได้กังวลเกี่ยวกับ sum([entry.stat().st_size for entry in os.scandir(file)])recursive-Ness หมายเหตุเอาต์พุตเป็นไบต์ / 1024 เพื่อรับ KB และ / (1024 * 1024) เพื่อรับ MB
weiji14

4
@ weiji14 sum(entry.stat().st_size for entry in os.scandir(file))ลดวงเล็บคือ ไม่มีเหตุผลที่จะทำรายการเพราะsumใช้ตัววนซ้ำเช่นกัน
Vedran Šego

8

คำตอบ monknut ดี แต่ล้มเหลวใน symlink ที่เสียดังนั้นคุณต้องตรวจสอบว่าเส้นทางนี้มีอยู่จริงหรือไม่

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

3
คุณอาจไม่ต้องการติดตาม symlinks lstatคุณควรใช้
asmeurer

8

คำตอบที่ยอมรับไม่ได้คำนึงถึงลิงค์ที่แข็งหรืออ่อนและจะนับไฟล์เหล่านั้นสองครั้ง คุณต้องการติดตามว่าคุณเห็น inode ใดบ้างและไม่เพิ่มขนาดไฟล์เหล่านั้น

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
ลองใช้os.lstat(แทนos.stat) ซึ่งหลีกเลี่ยงลิงก์สัญลักษณ์: docs.python.org/2/library/os.html#os.lstat
Peter Briggs

7

คำตอบของ Chris นั้นดี แต่สามารถใช้สำนวนได้มากขึ้นโดยใช้ set เพื่อตรวจสอบไดเรคทอรี่ที่เห็นซึ่งหลีกเลี่ยงการใช้ข้อยกเว้นสำหรับโฟลว์การควบคุม:

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
คำตอบของคริสก็ไม่ได้คำนึงถึงการเชื่อมโยงบัญชีหรือขนาดของไดเรกทอรีเอง df -sbฉันได้แก้ไขคำตอบของคุณตามการส่งออกของฟังก์ชั่นการแก้ไขอยู่ในขณะนี้เหมือนกัน
Creshal

7

ซับหนึ่งแบบเวียนเกิด:

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
มันไม่ใช่หนึ่งในสายการบิน อย่างไรก็ตามจะคำนวณขนาดโฟลเดอร์แบบเรียกซ้ำ (แม้ว่าโฟลเดอร์จะมีหลายโฟลเดอร์ภายใน) เป็นไบต์และให้ค่าที่ถูกต้อง
Venkatesh

ฉันใช้สิ่งนี้เพื่อใช้งานง่ายและทำงานครั้งแรกบน Windows
hum3

5

สำหรับส่วนที่สองของคำถาม

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

การใช้pathlibฉันขึ้นมาหนึ่งซับเพื่อให้ได้ขนาดของโฟลเดอร์:

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

และนี่คือสิ่งที่ฉันสร้างขึ้นเพื่อผลลัพธ์ที่มีการจัดรูปแบบอย่างดี:

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

การใช้งาน:

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

ฉันยังเจอคำถามนี้ซึ่งมีกลยุทธ์ขนาดกะทัดรัดและมีประสิทธิภาพมากขึ้นสำหรับการพิมพ์ขนาดไฟล์


4

คุณสามารถทำสิ่งนี้:

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

ในกรณีนี้ฉันยังไม่ได้ทดสอบผลลัพธ์ก่อนส่งคืนถ้าคุณต้องการคุณสามารถตรวจสอบได้ด้วยคำสั่ง getstatusoutput


เปรียบเทียบประสิทธิภาพการทำงานos.walkเพื่อตรวจสอบขนาดโฟลเดอร์ย่อยซ้ำ ๆ ได้อย่างไร
TomSawyer

4

สายการบินหนึ่งที่คุณพูด ... นี่คือสายการบินหนึ่ง:

sum([sum(map(lambda fname: os.path.getsize(os.path.join(directory, fname)), files)) for directory, folders, files in os.walk(path)])

แม้ว่าฉันอาจจะแยกมันออกและก็ไม่ทำการตรวจสอบ

หากต้องการแปลงเป็น kb โปรดดูไลบรารีที่ใช้ซ้ำได้เพื่อให้ได้ขนาดไฟล์ที่มนุษย์อ่านได้? และทำงานใน


4

สายไปงานเลี้ยงเล็กน้อย แต่ในบรรทัดเดียวโดยมีเงื่อนไขว่าคุณได้ติดตั้งglob2และhumanize โปรดทราบว่าใน Python 3 ค่าเริ่มต้นiglobมีโหมดเรียกซ้ำ วิธีการแก้ไขโค้ดสำหรับ Python 3 นั้นเป็นแบบฝึกหัดเล็กน้อยสำหรับผู้อ่าน

>>> 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 ในglobตัวรองรับการเรียกซ้ำ คุณสามารถใช้:glob.glob('/var/**', recursive=True)
adzenith

3

สคริปต์ต่อไปนี้จะพิมพ์ขนาดไดเรกทอรีของไดเรกทอรีย่อยทั้งหมดสำหรับไดเรกทอรีที่ระบุ นอกจากนี้ยังพยายามรับผลประโยชน์ (ถ้าเป็นไปได้) จากการแคชการเรียกใช้ฟังก์ชันเวียนเกิด หากมีการข้ามอาร์กิวเมนต์สคริปต์จะทำงานในไดเรกทอรีปัจจุบัน เอาต์พุตถูกเรียงลำดับตามขนาดไดเร็กทอรีจากใหญ่ที่สุดไปหาเล็กที่สุด ดังนั้นคุณสามารถปรับให้เข้ากับความต้องการของคุณ

PS ฉันใช้สูตร 578019 เพื่อแสดงขนาดไดเรกทอรีในรูปแบบที่เป็นมิตรกับมนุษย์ ( 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())

ตัวอย่างผลลัพธ์:

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)

แก้ไข: ย้าย null_decorator ด้านบนตามที่ผู้ใช้ 2233949 แนะนำ


สคริปต์ของคุณทำงานได้ดี แต่คุณต้องย้ายฟังก์ชัน null_decorator ด้านบนบรรทัด 'if sys.version_info> = ... ' มิฉะนั้นคุณจะได้รับ 'null_decorator' ไม่ใช่ข้อยกเว้นที่กำหนดไว้ ใช้งานได้ดีหลังจากนั้น
2233949

@ user2233949 ขอขอบคุณ! ฉันกำลังแก้ไขโค้ดให้สอดคล้องกัน
MaxU

3

ใช้ไลบรารี่ sh : โมดูลduทำ:

pip install sh

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

ถ้าคุณต้องการที่จะผ่าน Asterix ใช้globตามที่อธิบายไว้ที่นี่

ในการแปลงค่าในสิ่งที่มนุษย์อ่านได้ให้ใช้มนุษย์ :

pip install humanize

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

2

สำหรับการรับขนาดหนึ่งไฟล์มี os.path.getsize ()

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

รายงานในหน่วยไบต์


2

สำหรับสิ่งที่คุ้มค่า ... คำสั่ง tree ทำทั้งหมดนี้ได้ฟรี:

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

ฉันชอบ Python แต่วิธีแก้ปัญหาที่ง่ายที่สุดก็คือไม่ต้องใช้รหัสใหม่


@ Abdur-RahmaanJanhangeer นี่เป็นเรื่องจริง นี่เป็นเรื่องจริง
meh

2

มันมีประโยชน์:

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

ฉันใช้ python 2.7.13 กับscandirและนี่คือฟังก์ชั่น recursive แบบหนึ่งซับเพื่อให้ได้ขนาดทั้งหมดของโฟลเดอร์:

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

เมื่อคำนวณขนาดของไดเร็กทอรีย่อยแล้วควรอัปเดตขนาดโฟลเดอร์ของพาเรนต์และจะดำเนินต่อไปจนกระทั่งถึงรูทพาเรนต์

ฟังก์ชั่นต่อไปนี้คำนวณขนาดของโฟลเดอร์และโฟลเดอร์ย่อยทั้งหมด

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 คุณสามารถทำได้:

ติดตั้งโมดูล pywin32 โดยเรียกใช้:

pip ติดตั้ง pywin32

แล้วเข้ารหัสต่อไปนี้:

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

นี่คือหนึ่งซับที่ทำซ้ำ (ตัวเลือกแบบเรียกซ้ำที่มีอยู่ใน 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))


0

สคริปต์นี้จะบอกคุณว่าไฟล์ใดมีขนาดใหญ่ที่สุดใน CWD และยังบอกให้คุณทราบว่าไฟล์นั้นอยู่ในโฟลเดอร์ใด สคริปต์นี้ใช้งานได้กับฉันใน win8 และ 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

เป็นที่ยอมรับว่าเป็นแฮ็คชนิดหนึ่งและทำงานบน Unix / Linux เท่านั้น

มันตรงกับdu -sb .เพราะในผลนี้เป็น Python bash wrapper ที่รันdu -sb .คำสั่ง

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

ฉันมาสายนิดหน่อย (และใหม่) ที่นี่ แต่ฉันเลือกที่จะใช้โมดูลย่อยและบรรทัดคำสั่ง 'du' กับ Linux เพื่อดึงค่าที่ถูกต้องสำหรับขนาดโฟลเดอร์เป็น MB ฉันต้องใช้ if และ elif สำหรับโฟลเดอร์รูทเพราะมิฉะนั้นกระบวนการย่อยทำให้เกิดข้อผิดพลาดเนื่องจากค่าที่ไม่ใช่ศูนย์กลับมา

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

รับขนาดไดเรกทอรี

คุณสมบัติของการแก้ปัญหา:

  • ส่งคืนทั้งคู่: ขนาดที่ปรากฏ (จำนวนไบต์ในไฟล์) และพื้นที่ดิสก์จริงที่ไฟล์ใช้
  • นับไฟล์ที่เชื่อมโยงอย่างหนักเพียงครั้งเดียว
  • นับ symlink แบบเดียวกับที่duทำ
  • ไม่ใช้การเรียกซ้ำ
  • ใช้st.st_blocksสำหรับพื้นที่ดิสก์ที่ใช้จึงทำงานได้กับระบบที่เหมือน Unix เท่านั้น

รหัส:

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)

ตัวอย่างการใช้งาน:

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

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

ขนาดไฟล์ที่มนุษย์อ่านได้

คุณสมบัติของการแก้ปัญหา:

รหัส:

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)

ตัวอย่างการใช้งาน:

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


0

งูหลาม 3.6+ขนาดโฟลเดอร์ / ไฟล์ recursive os.scandirใช้ ในฐานะที่เป็นที่มีประสิทธิภาพในขณะที่คำตอบโดย @blakev แต่สั้นและใน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

ฉันเขียนฟังก์ชั่นนี้ซึ่งทำให้ฉันมีขนาดโดยรวมที่ถูกต้องของไดเรกทอรีฉันพยายามอื่น ๆ สำหรับการแก้ปัญหาแบบวนซ้ำกับ os.walk แต่ฉันไม่รู้ว่าทำไมผลลัพธ์ที่ได้จึงน้อยกว่าขนาดจริงเสมอ (บน Ubuntu 18 env) ฉันต้องทำสิ่งผิดปกติ แต่ใครสนใจเขียนสิ่งนี้ได้ผลดีที่สุด

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.