이 특정 바퀴를 다시 발명하기 전에 파이썬을 사용하여 디렉토리의 크기를 계산하는 데 좋은 루틴을 가진 사람이 있습니까? 루틴이 크기를 Mb / Gb 등으로 멋지게 포맷하면 매우 좋을 것입니다.
tree
* nix 시스템 의 명령은이 모든 것을 무료로 수행합니다. tree -h -d --du /path/to/dir
.
du -sh /path/to/dir/*
이 특정 바퀴를 다시 발명하기 전에 파이썬을 사용하여 디렉토리의 크기를 계산하는 데 좋은 루틴을 가진 사람이 있습니까? 루틴이 크기를 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을 사용하는 재미를위한 oneliner ( 하위 디렉토리는 포함하지 않음 ) :
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 플랫폼에서 일회성 인 경우 평소처럼 재귀가 포함 된 한 줄짜리 서식을 지정할 수 있습니다. 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
다음은 "du -sb"를 실행할 때와 정확히 동일한 바이트를 반환하는 재귀 함수 (모든 하위 폴더와 해당 파일의 크기를 재귀 적으로 합한 것)입니다. 리눅스에서 ( "."는 "현재 폴더"를 의미합니다) :
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("."))
파이썬 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
반복자를 가져 오기 때문에 목록을 만들 이유가 없습니다 .
허용되는 답변은 하드 링크 또는 소프트 링크를 고려하지 않으며 해당 파일을 두 번 계산합니다. 본 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()
Chris의 대답은 좋지만 보이는 디렉토리를 확인하기 위해 세트를 사용하여 관용적으로 만들 수 있으며 제어 흐름에 예외를 사용하지 않아도됩니다.
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
하여 폴더의 크기를 얻기 위해이 하나의 라이너를 찾았습니다.
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]
이 경우 명령을 사용하여 결과를 확인할 수 있도록 반환하기 전에 결과를 테스트하지 않았습니다.
os.walk
하위 폴더 크기를 재귀 적으로 확인하는 데 사용하는 성능과 비교하여 성능은 어떻습니까?
당신이 말하는 1 개의 강선… 여기에 1 개의 강선이 있습니다 :
sum([sum(map(lambda fname: os.path.getsize(os.path.join(directory, fname)), files)) for directory, folders, files in os.walk(path)])
아마 그것을 분리하고 검사를 수행하지는 않지만.
KB로 변환하려면 재사용 가능한 라이브러리를 참조 하여 사람이 읽을 수있는 파일 크기 버전을 얻으시겠습니까? 그리고 그것을 작동
파티에 약간 늦었지만 한 줄에 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)
다음 스크립트는 지정된 디렉토리에 대한 모든 서브 디렉토리의 디렉토리 크기를 인쇄합니다. 또한 재귀 함수 호출을 캐싱함으로써 (가능한 경우) 이익을 얻으려고 시도합니다. 인수가 생략되면 스크립트는 현재 디렉토리에서 작동합니다. 출력은 가장 큰 것에서 가장 작은 것까지 디렉토리 크기별로 정렬됩니다. 따라서 필요에 맞게 조정할 수 있습니다.
추신 : 인간 친화적 인 형식으로 디렉토리 크기를 표시하기 위해 레시피 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)
편집 : 사용자 2233949 권장으로 null_decorator를 위로 옮겼습니다.
편리합니다 :
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
나는 scandir 과 함께 python 2.7.13을 사용 하고 있으며 폴더의 전체 크기를 가져 오는 한 줄짜리 재귀 함수가 있습니다.
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 install 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")
분명히 이것은 일종의 해킹이며 유닉스 / 리눅스에서만 작동합니다.
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 단위로 검색하도록 선택했습니다. 그렇지 않으면 하위 프로세스에서 0이 아닌 값이 반환되어 오류가 발생하기 때문에 루트 폴더에 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
된 디스크 공간에 사용되므로 유닉스 계열 시스템에서만 작동코드:
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 루프 솔루션을 시도했지만 최종 결과가 항상 실제 크기보다 작은 이유를 모른다 (우분투 18 env). 나는 뭔가 잘못했을 것입니다.