파이썬으로 이것저것 만들고 공부 중입니다 ^^
얼마 전에 C 드라이브 하드디스크 공간이 없길래, 좀 더 자세히 알고 싶기도 하고 공부 삼아 만들어 봤습니다 (이미 폴더 크기 구하는 프로그램들이 많음에도 ~)
프로그램은 간단합니다.
실행하면 폴더(하위 포함) 크기를 구하고 싶은 드라이브나 폴더를 입력하고 Run 해 주면 됩니다.
결과는 엑셀 파일로 만드는데요
그림처럼 폴더와 파일 2개의 sheet 를 만들고 각 sheet 에 폴더 크기와 파일 크기 역순으로 10,000 개씩 기록 합니다 (너무 많으면 엑셀 파일에 쓰다 죽기도 해서 만개로 제한)
프로그램 코드는 아래와 같습니다
import operator
import sys
import os
from PyQt5.QtWidgets import *
import pandas as pd
gExcelFile = 'foldersize.xlsx'
class CFolderSize:
def getFolderSize(self, path, caller, parentPath):
if path not in caller.dicFolder:
caller.dicFolder[path] = {'size': 0, 'folders': 0, 'files': 0, 'error': False}
if (parentPath != ''):
if parentPath not in caller.dicFolder:
caller.dicFolder[parentPath] = {'size': 0, 'folders': 0, 'files': 0, 'error': False}
try:
for fname in os.listdir(path):
fullname = os.path.join(path, fname)
if os.path.isdir(fullname):
caller.dicFolder[path]['folders'] += 1
if False == self.getFolderSize(fullname, caller, path):
# if parentPath != '@root@':
# caller.dicFolder[parentPath]['error'] = True
continue
if os.path.isfile(fullname):
caller.dicFolder[path]['files'] += 1
size = os.path.getsize(fullname)
caller.dicFolder[path]['size'] += size
caller.dicFile[fullname] = size
except:
print('exception 발생', path, parentPath)
caller.dicFolder[path]['error'] = True
return False
if (parentPath != '@root@'):
caller.dicFolder[parentPath]['size'] += caller.dicFolder[path]['size']
print(path, 'folder size=', caller.dicFolder[path]['size'],
'folders#= ', caller.dicFolder[path]['folders'],
'files#= ', caller.dicFolder[path]['files'])
return True
def convertSizeToString(self, size):
if size == 0:
return ''
gb, rest = divmod(size, 1000000000)
if (gb > 0):
return '%s GB (%s)' % (format(gb, ','), format(size, ','))
mb, rest = divmod(rest, 1000000)
if (mb > 0):
return '%s MB (%s)' % (format(mb, ','), format(size, ','))
kb, rest = divmod(rest, 1000000)
if (kb > 0):
return '%s KB (%s)' % (format(kb, ','), format(size, ','))
return '%s' % (format(size, ','))
class MyWindow(QMainWindow):
def __init__(self):
super().__init__()
self.dicFolder = {}
self.dicFile = {}
self.dicSortedFolder = []
self.dicSortedFile = []
# 윈도우 버튼 배치
self.setWindowTitle("Folder Size")
nH = 20
self.pathEdit = QLineEdit("", self)
self.pathEdit.move(20, nH)
self.pathEdit.resize(300, 30)
# self.pathEdit.textChanged.connect(self.pathEditChanged)
self.pathEdit.setText('00660')
self.label = QLabel('폴더', self)
self.label.move(340, nH)
nH += 50
btnRun = QPushButton("Run", self)
btnRun.move(20, nH)
btnRun.clicked.connect(self.btnRun_clicked)
nH += 50
self.setGeometry(300, 300, 400, nH)
self.pathEdit.setText('c:\\')
def btnRun_clicked(self):
findPath = self.pathEdit.text()
if findPath[-1] != "\\":
findPath += "\\"
if not os.path.isdir(findPath):
print('존재하지 않는 폴더입니다.', findPath)
return
objFolder = CFolderSize()
self.dicFolder = {}
self.dicFile = {}
self.dicSortedFolder = []
self.dicSortedFile = []
objFolder.getFolderSize(findPath, self, '@root@')
# print('-----------------------------------------')
# max = 20
# if max > len(self.dicFolder) :
# max = len(self.dicFolder)
# print('TOP 20 BIG SIZE FOLDERS')
self.dicSortedFolder = sorted(self.dicFolder.items(), key=lambda x: x[1]['size'], reverse=True)
# for i in range(0, max) :
# print(self.dicSortedFolder[i][0], objFolder.convertSizeToString(self.dicSortedFolder[i][1]['size']))
# print('-----------------------------------------')
# print('TOP 20 BIG SIZE FILES')
# max = 20
# print(self.dicFile)
# if max > len(self.dicFile) :
# max = len(self.dicFile)
self.dicSortedFile = sorted(self.dicFile.items(), key=operator.itemgetter(1), reverse=True)
# for i in range(0, max) :
# print(self.dicSortedFile[i][0], objFolder.convertSizeToString(self.dicSortedFile[i][1]))
print('엑셀 내보내기 시작')
self.exportExcel(self.dicSortedFolder, self.dicSortedFile)
def exportExcel(self, folderlist, filelist):
i = 0
writer = pd.ExcelWriter(gExcelFile, engine='xlsxwriter')
df = pd.DataFrame(columns=['path', 'size', '폴더수', '파일수'])
for folder in folderlist:
i += 1
if (i > 10000) :
print('폴더리스트 저장은 10000개만 저장, 전체 폴더 개수 %d' %(len(folderlist)))
break
item = {}
item['path'] = folder[0]
item['size'] = folder[1]['size']
item['폴더수'] = folder[1]['folders']
item['파일수'] = folder[1]['files']
df.loc[len(df)] = item
# Convert the dataframe to an XlsxWriter Excel object.
df.to_excel(writer, sheet_name='folders')
i = 0
df2 = pd.DataFrame(columns=['filename', 'size', 'fullpath'])
for file in filelist:
i += 1
if (i > 10000) :
print('파일리스트 저장은 10000 개만 저장, 전체 파일 수 %d' %(len(filelist)))
break
item = {}
path = file[0]
item['filename'] = os.path.basename(path)
item['size'] = file[1]
item['fullpath'] = path
df2.loc[len(df2)] = item
df2.to_excel(writer, sheet_name='files')
# Close the Pandas Excel writer and output the Excel file.
writer.save()
os.startfile(gExcelFile)
return
if __name__ == "__main__":
app = QApplication(sys.argv)
myWindow = MyWindow()
myWindow.show()
app.exec_()
♨ 예전에 프로그램 공부 할 때 재귀 함수의 단점을 열심히 들었던 거 같은데, 위 코드처럼 아름답게(?) 하위 폴더를 탐색하는 코드에서는 재귀 함수가 멋지게 보이네요. 단점은 내 알바 아니고 ^^
♨ 폴더 접근 시 오류가 나는 폴더들이 있습니다. 요건 예외 처리하도록 되어 있습니다. 특히 최근 OS 에서는 탐색기에서 조차 제대로 진입 못하는 폴더가 많네요. 그래서 프리웨어로 유명한 폴더 구하기 프로그램도 에러를 내 뱉는 경우가 많습니다(제대로 업데이트가 안되다 보니)
♨ 파이썬으로 엑셀 다루기는 참 쉽습니다. 이 예제에서는 SHEET 를 여러개 쓰는 코드가 포함되어 있으니 참고 하세요 ~
♨ 하드디스크에 폴더 수나 파일 수는 예상보다 훨씬 많습니다. 요걸 모두 딕셔너리에 담고, 소팅도 하고 엑셀에도 씁니다. 파이썬이 올매나 하드한 작업을 견뎌내는 지 고문용(?) 으로 좋네요
'개발 > 파이썬' 카테고리의 다른 글
[파이썬] 선물 분 차트 그리기(matplotlib) (4) | 2018.02.18 |
---|---|
[파이썬] 지정한 폴더/확장자에서 텍스트 일괄 변경 (0) | 2018.02.06 |
[파이썬] 파일 옮기기 (0) | 2017.12.30 |
[파이썬] 리스트/딕셔너리 정렬하기 (0) | 2017.12.11 |
[파이썬] Creon Plus 를 이용해서 KOSPI200 종목 시세 가져오기 (0) | 2017.10.15 |
[파이썬] 안드로이드 프로젝트에서 자바 클래스 레퍼런스 카운트 구하기 (0) | 2017.10.14 |
댓글