MapleStory Finger Point

미니 프로젝트/파일 자동 삭제

파이썬으로 파일 자동 삭제 프로그램 만들기

吳鍾振 2022. 2. 17. 15:12

회사에서 만드는 프로그램의 특성상 데이터 저장으로 하드를 되게 많이 쓰고 있다.

주기적으로 저장 공간 관리를 직접 하는데 너무 귀찮아서 하나 만들어 보았다.

사용한 모듈은 osshutilpsutil이다.
psutil은 외부 모듈으로 pip install psutil로 설치하여야 한다.

일단 알고리즘부터 짠 다음, GUI를 통해 만들어보려 한다.

코드는 아래와 같다.

#!/usr/bin/env python3
#
# Copyright 2021-2022 9th grade 5th class.
#
# Authors:
#     5jx2oh@gmail.com


import os
import sys
import shutil
import psutil


class FileAutoDelete:
    """
    Delete the oldest folder from the path specified by user
    """

    def __init__(self):

        drive = []
        # Save all of the user's drives in drive variable.
        for i in range(len(psutil.disk_partitions())):
            drive.append(str(psutil.disk_partitions()[i])[18:19])

        # Set the drive as the reference to D
        self.diskLabel = 'D://'
        self.total, self.used, self.free = shutil.disk_usage(self.diskLabel)

        self.path = None

        try:
            self.need_storage = int(input(f'How much storage space do you want? '
                                          f'(Now you have {self.byte_transform(self.free, "GB")} GB) : '))
        except ValueError:
            print('Insert only number!!!!!!')
            sys.exit()
        self.main()

    def byte_transform(self, bytes, to, bsize=1024):
        """
        Unit conversion of byte received from shutil

        :return: Capacity of the selected unit (int)
        """
        unit = {'KB': 1, 'MB': 2, 'GB': 3, 'TB': 4}
        r = float(bytes)
        for i in range(unit[to]):
            r = r / bsize
        return int(r)

    def delete_oldest_files(self, path, minimum_storage_GB: int):
        """
        The main function of this Program
        Find oldest file and proceed with deletion

        :param path: Path to proceed with a auto-delete
        :param minimum_storage_GB: Minimum storage space desired by the user
        :return: None
        """
        is_old = {}

        while minimum_storage_GB >= self.byte_transform(self.free, 'GB'):

            for f in os.listdir(path):

                i = os.path.join(path, f)
                is_old[f'{i}'] = int(os.path.getctime(i))

            value = list(is_old.values())
            key = {v: k for k, v in is_old.items()}
            oldest = key.get(min(value))

            box = input(f'Are you sure to delete "{oldest}" folder?')
            if box == "":
                print('yes')
                # Main syntax for deleting folders
                shutil.rmtree(oldest)
            else:
                print('no')
                sys.exit()

        print('Already you have enough storage.')

    def main(self):
        """
        Delete files by comparing "need_storage" with the current storage space

        :return: None
        """
        # If storage space required is more than current storage space
        if self.need_storage >= self.byte_transform(self.free, 'GB'):
            # Specify the Vista folder path of the d drive as a path variable
            self.path = os.path.join(self.diskLabel, 'vista')
            try:
                self.delete_oldest_files(self.path, self.need_storage)
            except FileNotFoundError:
                print(f'[{self.path}] - Not Found Error')

        else:
            print('Input storage again')


if __name__ == "__main__":

    start = FileAutoDelete()

        # [28]
        self.diskLabel = 'D://'

우선 예시로 D 드라이브를 적용하였으며, GUI로 구현 시 사용자가 드라이브를 선택할 수 있도록 제작 예정이다.

        # [29]
        self.total, self.used, self.free = shutil.disk_usage(self.diskLabel)

total - 드라이브의 총 저장 공간
used - 드라이브의 사용한 공간
free - 드라이브의 남은 공간
출력 시 기본 형태는 바이트 단위로 출력된다.

        # [33]
        try:
            self.need_storage = int(input(f'How much storage space do you want? '
                                          f'(Now you have {self.byte_transform(self.free, "GB")} GB) : '))

현재 드라이브의 남은 공간을 보여주며, 사용자에게 얼마의 저장 공간을 원하는지 물어본다.

byte_transform 함수는 위에서 말한 total, used, free가 바이트 단위로 나오기 때문에, 단위 변환해주는 함수이다.

        # [64]
        while minimum_storage_GB >= self.byte_transform(self.free, 'GB'):

delete_oldest_files 함수 내부 구문으로, 현재 드라이브의 남은 공간이 사용자가 원하는 저장 공간보다 크거나 같아질 때까지 반복한다.

예를 들어 900GB를 차지하고 있는데 사용자가 1TB 공간을 원하면, 100GB를 지울 때까지 반복함

            # [73]
            oldest = key.get(min(value))

value는 path에 있는 폴더, 파일들의 생성된 시간(epoch 단위)을 나타내므로 가장 작은 시간(=오래된) 시간을 가진 폴더 및 파일명을 oldest로 저장한다.

                # [79]
                shutil.rmtree(oldest)

이 프로그램의 메인이 되는 구문, 딱 한 줄이다

shutil.rmtree(path, ignore_errors=False, onerror=None)
전체 디렉토리 트리를 삭제한다. path는 디렉토리를 가리켜야 한다.
ignore_errors가 참이면 삭제 실패로 인한 에러는 출력되지 않으며 그냥 넘어간다.
onerror로 지정된 처리기를 호출하여 처리하거나, 생략하면 예외가 발생한다.
그런데 주로 path만 사용하므로 나머지 인자는 사용하지 않았다.

shutil에서 삭제할 수 있는 또 다른 함수 rmdir, remove 가 있는데
간단하게 rmdir은 빈 폴더만 삭제 가능, remove는 파일만 삭제 가능하기 때문에
안에 파일이 있든 말든 그냥 다 삭제해버리는 rmtree를 사용하였다. 그만큼 주의해서 사용해야 할 것이다.
나도 코드 테스트 해본다고 날려먹은 파일이 한 두 개가 아니다..

        # [93]
        if self.need_storage >= self.byte_transform(self.free, 'GB'):

64번째 줄의 구문과 같은 맥락이다.
입력받은 값이 현재 저장 공간 용량보다 크거나 같으면 다음 구문을 실행한다.

            # [94]
            # Specify the Vista folder path of the d drive as a path variable
            self.path = os.path.join(self.diskLabel, 'vista')

 diskLabel은 'D:/'로 설정해놓았기 때문에, path는 'D:/vista'이다.

 

이렇게 일단 알고리즘 정도만 짜보았다.
물론 이 코드도 완벽한게 아니고 후다닥 만든 거기 때문에 조금씩 다듬으며 GUI와 연동해야 할 것이다.

예시

테스트를 위해 잠시 삭제하는 구문을 주석처리 하였는데 이런식으로 저장 공간이 1000GB가 될 때까지 반복한다.

https://github.com/Oh-JongJin/AutoFileDelete

 

GitHub - Oh-JongJin/AutoFileDelete

Contribute to Oh-JongJin/AutoFileDelete development by creating an account on GitHub.

github.com

 

반응형