この特定のホイールを再発明する前に、Pythonを使用してディレクトリのサイズを計算するための素晴らしいルーチンを誰かが持っていますか?ルーチンがMb / Gbなどでサイズを適切にフォーマットすることは非常に良いでしょう
tree* nixシステムのコマンドは、これらすべてを無料で実行します。tree -h -d --du /path/to/dir。
du -sh /path/to/dir/*
この特定のホイールを再発明する前に、Pythonを使用してディレクトリのサイズを計算するための素晴らしいルーチンを誰かが持っていますか?ルーチンがMb / Gbなどでサイズを適切にフォーマットすることは非常に良いでしょう
tree* nixシステムのコマンドは、これらすべてを無料で実行します。tree -h -d --du /path/to/dir。
du -sh /path/to/dir/*
回答:
これはすべてのサブディレクトリを歩きます。ファイルサイズの合計:
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')
そして、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())
st_size、シンボリックリンクを追跡しない場合は、を使用する必要があるため、使用する必要がありますlstat。
これまでに提案されたアプローチの中には、再帰を実装するものもあれば、シェルを使用するものや、適切にフォーマットされた結果を生成しないものもあります。コードがLinuxプラットフォームで1回限りの場合、再帰を含めて、通常どおりフォーマットを1行で行うことができます。print最後の行のを除いて、現在のバージョンのpython2andで機能し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
これは再帰関数です(すべてのサブフォルダーとそれぞれのファイルのサイズを再帰的に合計します)。これは、「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("."))
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
sum([entry.stat().st_size for entry in os.scandir(file)])。出力はバイト単位であり、/ 1024はKBを取得し、/(1024 * 1024)はMBを取得します。
sum(entry.stat().st_size for entry in os.scandir(file))。sumイテレータも取るので、リストを作成する理由はありません。
monknut回答は良いですが、壊れたシンボリックリンクで失敗するので、このパスが実際に存在するかどうかも確認する必要があります
if os.path.exists(fp):
total_size += os.stat(fp).st_size
lstat。
受け入れられた回答はハードリンクまたはソフトリンクを考慮せず、それらのファイルを2回カウントします。表示したiノードを追跡し、それらのファイルのサイズを追加したくない場合。
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()
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
df -sbます。
再帰的なワンライナー:
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))])
質問の後半について
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])
を使用してpathlib、フォルダーのサイズを取得するために次の1行を作成しました。
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)
私もこの質問に出くわしました。これには、ファイルサイズを印刷するためのよりコンパクトでおそらくより優れた戦略があります。
あなたはこのようなことをすることができます:
import commands
size = commands.getoutput('du -sh /path/').split()[0]
この場合、返す前に結果をテストしていません。必要に応じて、commands.getstatusoutputで結果を確認できます。
os.walkサブフォルダーのサイズを再帰的に確認するために使用する場合と比較して、パフォーマンスはどうですか?
あなたが言うワンライナー...これがワンライナーです:
sum([sum(map(lambda fname: os.path.getsize(os.path.join(directory, fname)), files)) for directory, folders, files in os.walk(path)])
私はおそらくそれを分割し、チェックを実行しません。
kbに変換するには、再利用可能なライブラリを参照して、人間が読めるバージョンのファイルサイズを取得してください。そしてそれで働く
少し遅れてパーティーへのが、1つのラインであなたが持っていることを提供glob2をしてヒト化するインストール。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'
globは再帰をサポートしています。あなたは使用することができます:glob.glob('/var/**', recursive=True)
次のスクリプトは、指定されたディレクトリのすべてのサブディレクトリのディレクトリサイズを出力します。また、(可能であれば)再帰関数の呼び出しをキャッシュすることでメリットを得ようとします。引数を省略すると、スクリプトは現在のディレクトリで動作します。出力は、ディレクトリサイズの大きい順に並べ替えられます。だからあなたはあなたのニーズにそれを適応させることができます。
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)
編集:user2233949が推奨されているため、null_decoratorを上に移動
1つのファイルのサイズを取得するために、os.path.getsize()があります
>>> import os
>>> os.path.getsize("/path/file")
35L
バイト単位で報告されます。
便利です:
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
私はとのpython 2.7.13を使用していSCANDIR、ここで私のワンライナー再帰関数は、フォルダの合計サイズを取得することです:
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
サブディレクトリのサイズが計算されると、親のフォルダサイズが更新され、ルートの親に到達するまでこれが続きます。
次の関数は、フォルダーとそのすべてのサブフォルダーのサイズを計算します。
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
Windows OSを使用している場合は、次のことができます。
起動して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))
このスクリプトは、CWDで最大のファイルと、ファイルがどのフォルダーにあるかを通知します。このスクリプトは、win8および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")
確かに、これは一種のハックで、Unix / Linuxでのみ機能します。
du -sb .実際にはこれはdu -sb .コマンドを実行するPython bashラッパーなので、一致します。
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])
私は少し遅れました(そして新しい)が、サブプロセスモジュールとLinuxの 'du'コマンドラインを使用して、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
ソリューションのプロパティ:
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'
pathlibを使用してPython 3.6で動作するソリューション。
from pathlib import Path
sum([f.stat().st_size for f in Path("path").glob("**/*")])
Python 3.6+を使用した再帰的なフォルダー/ファイルサイズos.scandir。@blakev の回答と同じくらい強力ですが、短く、EAFPの Pythonスタイルです。
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
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で他のforループソリューションを試しましたが、最終結果が常に実際のサイズよりも小さい理由がわかりません(ubuntu 18 envの場合)。私は何か間違ったことをしたにちがいありませんが、これを書いた人は完璧にうまくいきます。