ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [파이썬] 폴더 크기 구하기
    개발/파이썬 2017.12.30 15:23

    파이썬으로 이것저것 만들고 공부 중입니다 ^^

    얼마 전에 C 드라이브 하드디스크 공간이 없길래, 좀 더 자세히 알고 싶기도 하고 공부 삼아 만들어 봤습니다 (이미 폴더 크기 구하는 프로그램들이 많음에도 ~)


    프로그램은 간단합니다. 

    실행하면 폴더(하위 포함) 크기를 구하고 싶은 드라이브나 폴더를 입력하고 Run 해 주면 됩니다.



    결과는 엑셀 파일로 만드는데요 

    그림처럼 폴더와 파일 2개의 sheet 를 만들고 각 sheet 에 폴더 크기와 파일 크기 역순으로 10,000 개씩 기록 합니다 (너무 많으면 엑셀 파일에 쓰다 죽기도 해서 만개로 제한)

    프로그램 코드는 아래와 같습니다 

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    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(30030)
            #        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(300300400, 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_()
    cs


    ♨ 예전에 프로그램 공부 할 때 재귀 함수의 단점을 열심히 들었던 거 같은데, 위 코드처럼 아름답게(?) 하위 폴더를 탐색하는 코드에서는 재귀 함수가 멋지게 보이네요. 단점은 내 알바 아니고 ^^

    ♨ 폴더 접근 시 오류가 나는 폴더들이 있습니다. 요건  예외 처리하도록 되어 있습니다. 특히 최근 OS 에서는 탐색기에서 조차 제대로 진입 못하는 폴더가 많네요. 그래서 프리웨어로 유명한 폴더 구하기 프로그램도 에러를 내 뱉는 경우가 많습니다(제대로 업데이트가 안되다 보니)

    ♨  파이썬으로 엑셀 다루기는 참 쉽습니다. 이 예제에서는 SHEET 를 여러개 쓰는 코드가 포함되어 있으니 참고 하세요 ~

    ♨ 하드디스크에 폴더 수나 파일 수는 예상보다 훨씬 많습니다. 요걸 모두 딕셔너리에 담고, 소팅도 하고 엑셀에도 씁니다. 파이썬이 올매나 하드한 작업을 견뎌내는 지 고문용(?) 으로 좋네요 



    댓글 0

Designed by black7375.