Python实现文件管理系统

狂码了一天,各种修改优化,最后决定就这样,其实最开始就只打算能批量重命名一下图片就ok的

下面是代码实现部分,注释还是比较清楚的

代码实现

import os   # 操作系统库
import re   # 正则表达式库
import sys  # 系统库
import shutil   # 删除目录
from colorama import init, Fore, Back, Style    # 改变输出文字颜色


# 菜单类
class Menu:
    def __init__(self):
        self.rename = Rename()
        self.delete = Delete()
        self.choices = {
            "1": self.rename.run1,
            "2": self.delete.run2,
            "3": self.quit
        }   # 定义包含序号和操作的字典

    def show_menu(self):
        print(Fore.LIGHTRED_EX + "*****欢迎来到Xherlock的文件管理系统*****")
        print(Fore.LIGHTRED_EX + "          (1) 重命名")
        print(Fore.LIGHTRED_EX + "          (2) 删除")
        print(Fore.LIGHTRED_EX + "          (3) 退出")

    def run(self):
        while True:
            self.show_menu()
            try:
                choice = input("请输入你的选择(数字)")
            except Exception as e:
                print("请输入有效选项!")
                continue
            choice = str(choice).strip()    # 分割空白符和回车符
            action = self.choices.get(choice)   # 获取选择的操作
            if action:
                action()
            else:
                print("没有{0}这个选项!请重新选择".format(choice))

    def quit(self):
        print(Fore.LIGHTBLUE_EX + "感谢您使用Xherlock的文件管理系统!")
        sys.exit(0)


# 重命名类
class Rename:
    def __init__(self):
        self.choices = {
            "1": self.rename_file,
            "2": self.rename_files,
            "3": " "
        }

    def show_rename_menu(self):
        print(Fore.LIGHTYELLOW_EX + "*****重命名*****")
        print(Fore.LIGHTYELLOW_EX + "  (1) 单个")
        print(Fore.LIGHTYELLOW_EX + "  (2) 批量")
        print(Fore.LIGHTYELLOW_EX + "  (3) 退出")

    def run1(self):
        while True:
            self.show_rename_menu()
            try:
                choice1 = input("请输入你的选择(数字)")
            except Exception as e:
                print("请输入有效选项!")
                print("---------------------------------------------------")
                continue
            choice1 = str(choice1).strip()
            action = self.choices.get(choice1)
            if action:
                if choice1 == "3":
                    break
                action()
            else:
                print("没有{0}这个选项!请重新选择".format(choice1))

    def rename_file(self):
        """
        重命名单个文件:
        输入所要重命名文件所在目录的绝对路径,展示列表后选择相应序号进行重命名
        依次输入新名字,判断是否要修改后缀名(后缀名不得包含非法字符),若需要修改后缀名,需要输入新后缀名
        最后展示修改前后的文件列表,对比可以看出所作的更改
        中间在重命名后会进行判断新名字是否已存在,若存在返回重新尝试的提醒
        """
        try:
            path = input("请输入重命名文件路径:")
            currentpath = os.getcwd()   # 得到当前工作目录
            os.chdir(path)              # 将当前工作目录修改为待修改文件所在目录
            filelist = os.listdir(path)     # 获取目录下的文件列表
            i = 1       # 初始化计数器
            print(">>>文件列表")
            for filename in filelist:
                print(f"[{i}] {filename}")  # 输出文件列表
                i += 1
            print(Fore.LIGHTRED_EX + "!建议重命名文件而不是文件夹")
            num = input("请输入你要修改文件的序号:")    # 输入选择重命名的文件序号
            name = os.path.splitext(filelist[int(num) - 1])
            suffix = name[1]        # 使用os库下的函数分割文件名来获取后缀名,正则表达式有点麻烦
            new_name = input("请输入新文件名:")
            change_suffix = input("是否要修改后缀名(y/n):")
            if change_suffix == 'y' or change_suffix == 'Y':
                new_suffix = input("请输入新的后缀名(不得包含'?\ * | “ < > : /'):")
                print("修改前:" + str(os.listdir(path)))
                os.rename(filelist[int(num) - 1], (str(new_name) + '.' + new_suffix))
            elif change_suffix == 'n' or change_suffix == 'N':
                print("修改前:" + str(os.listdir(path)))
                os.rename(filelist[int(num) - 1], (str(new_name) + suffix))
            else:
                print("输入错误!")
                return
            print("---------------------------------------------------")
            os.chdir(currentpath)   # 改回程序运行前的工作目录
            sys.stdin.flush()       # 刷新
            print("修改后:" + str(os.listdir(path)))  # 输出修改后文件夹中包含的文件
        except FileExistsError as e:    # 抛出重命名文件已存在的错误
            print("文件已存在,请重新尝试命名!")

    def rename_files(self):
        """
        批量重命名文件:
        输入所要批量重命名文件所在目录的绝对路径,先选择是否自定义批量修改
        在自定义批量修改模式下会先展示目录下的全部文件及其序号,然后输入想要重命名文件的序号(以英文逗号分隔)
        然后依次询问是否统一修改后缀名,是否自定义name+自动化数字,若不统一修改后缀名,则必须为图片格式
        若未选择该模式,就是按1-n命名
        依次输入新名字,判断是否要修改后缀名(后缀名不得包含非法字符),若需要修改后缀名,需要输入新后缀名
        最后展示修改前后的文件列表,对比可以看出所作的更改
        中间在重命名后会进行判断新名字是否已存在,若存在返回重新尝试的提醒
        """
        try:
            print("---------------------------------------------------")
            print(Fore.LIGHTRED_EX + "!建议批量修改的文件为同一类型格式,比如全是图片或word文档")
            path = input("请输入批量重命名文件的路径:")
            currentpath = os.getcwd()   # 得到进程当前工作目录
            os.chdir(path)              # 将当前工作目录修改为待修改文件夹的位置
            filelist = os.listdir(path)
            print("<自定义批量修改模式>:依据序号选择想要重命名的文件")
            flag0 = input("是否进入自定义批量修改模式(y/n):")
            if flag0 == 'y' or flag0 == 'Y':    # 自定义模式重命名
                num = 1
                print("文件列表>>>")
                for filename in filelist:
                    print(f"[{num}] {filename}")
                    num += 1
                num = input("请输入你要修改文件的序号(以逗号分隔):")
                numlist = num.split(',')
                flag1 = input("是否统一修改后缀名(y/n):")
                if flag1 == 'y' or flag1 == 'Y':
                    new_suffix = input("请输入新的后缀名(不得包含'?\ * | “ < > : /'):")
                flag2 = input("是否自定义文件名(y/n):")
                if flag2 == 'y' or flag2 == 'Y':
                    new_name = input("请输入新的文件名:")
                print("修改前:" + str(os.listdir(path)))
                i = 0
                for j in numlist:
                    i += 1
                    if flag1 == 'y' or flag1 == 'Y':
                        if flag2 == 'y' or flag2 == 'Y':
                            os.rename(filelist[int(j) - 1], (str(new_name) + str(i) + '.' + str(new_suffix)))
                        elif flag2 == 'n' or flag2 == 'N':
                            os.rename(filelist[int(j) - 1], (str(i) + '.' + str(new_suffix)))
                        else:
                            print("输入错误!")
                            return
                    elif flag1 == 'n' or flag1 == 'N':
                        pat = ".+\.(jpeg|jpg|png|gif|bmp)"  # 匹配文件名正则表达式
                        pattern = re.findall(pat, filelist[int(j) - 1])  # 进行匹配
                        if flag2 == 'y' or flag2 == 'Y':
                            os.rename(filelist[int(j) - 1], (str(new_name) + str(i) + '.' + pattern[0]))
                        elif flag2 == 'n' or flag2 == 'N':
                            os.rename(filelist[int(j) - 1], (str(i) + '.' + pattern[0]))
                        else:
                            print("输入错误!")
                            return
                    else:
                        print("输入错误!")
                        return

            elif flag0 == 'n' or flag0 == 'N':  # 非自定义模式重命名
                k = 1
                print("修改前:" + str(os.listdir(path)))
                for file in filelist:
                    name = os.path.splitext(filelist[int(k) - 1])
                    suffix = name[1]
                    os.rename(filelist[int(k) - 1], (str(k) + suffix))
                    k += 1
            else:
                print("输入错误!")
                return
            print("---------------------------------------------------")
            os.chdir(currentpath)  # 改回程序运行前的工作目录
            sys.stdin.flush()  # 刷新
            print("修改后:" + str(os.listdir(path)))  # 输出修改后文件夹中包含的文件
        except FileExistsError as e:
            print("文件已存在,请重新尝试!")


class Delete:
    def __init__(self):
        self.choices = {
            "1": self.del_folder,
            "2": self.del_file,
            "3": " "
        }

    def show_del_menu(self):
        print(Fore.LIGHTGREEN_EX + "*****删除*****")
        print(Fore.LIGHTGREEN_EX + " (1) 文件夹")
        print(Fore.LIGHTGREEN_EX + " (2) 文件")
        print(Fore.LIGHTGREEN_EX + " (3) 退出")

    def run2(self):
        while True:
            self.show_del_menu()
            try:
                choice2 = input("请输入你的选择(数字)")
            except Exception as e:
                print("请输入有效选项!")
                print("---------------------------------------------------")
                continue
            choice2 = str(choice2).strip()
            action = self.choices.get(choice2)
            if action:
                if choice2 == "3":
                    break
                action()
            else:
                print("没有{0}这个选项!请重新选择".format(choice2))

    def del_folder(self):
        """
        删除文件夹
        """
        print("---------------------------------------------------")
        path = input("请输入删除文件夹的路径:")
        confirm = input("确认是否删除(y/n):")
        if confirm == 'y' or confirm == 'Y':
            if os.path.exists(path):
                shutil.rmtree(path)  # 必须得使用shutil库里的方法,os库没有权限删除目录
                print("删除成功!")
            else:
                print("文件夹不存在!")
        else:
            print("‘三思而后行’这句话很对")
            return

    def del_file(self):
        """
        删除文件:
        可以选择是删除一个还是多个文件
        """
        print("---------------------------------------------------")
        path = input("请输入删除文件所在目录:")
        filelist = os.listdir(path)
        i = 1
        print(">>>文件列表")
        for file in filelist:
            print(f'[{i}]{file}')
            i += 1
        choice = input("删除一个(y)或多个(n)文件(y/n):")
        if choice == 'y' or choice == 'Y':
            num = input("请输入你要删除文件的序号:")
            confirm = input("确认是否删除(y/n):")
            if confirm == 'y' or confirm == 'Y':
                new_path = path + '\\' + filelist[int(num) - 1]
                os.remove(new_path)
                print("删除成功!")
            elif confirm == 'n' or confirm == 'N':
                print("‘三思而后行’这句话很对")
                return
            else:
                print("输入错误!")
        elif choice == 'n' or choice == 'N':
            try:
                num = input("请输入你要删除文件的序号(用逗号分隔):")
                numlist = num.split(',')
                confirm = input("确认是否删除(y/n):")
                if confirm == 'y' or confirm == 'Y':
                    for i in numlist:
                        new_path = path + '\\' + filelist[int(i) - 1]
                        os.remove(new_path)
                    print("删除成功!")
                elif confirm == 'n' or confirm == 'N':
                    print("‘三思而后行’这句话很对")
                    return
                else:
                    print("输入错误!")
            except ValueError as e:
                print("输入序号错误!请重新操作")
        else:
            print("输入错误!")


if __name__ == '__main__':
    init(autoreset=True)
    # ASCII字符签名,好看而已
    print(Fore.LIGHTMAGENTA_EX + "___   ___  __    __   _______ .______       __        ______     ______  __  ___")
    print(Fore.LIGHTMAGENTA_EX + "\  \ /  / |  |  |  | |   ____||   _  \     |  |      /  __  \   /      ||  |/  /")
    print(Fore.LIGHTMAGENTA_EX + " \  V  /  |  |__|  | |  |__   |  |_)  |    |  |     |  |  |  | |  ,----'|  '  / ")
    print(Fore.LIGHTMAGENTA_EX + "  >   <   |   __   | |   __|  |      /     |  |     |  |  |  | |  |     |    <  ")
    print(Fore.LIGHTMAGENTA_EX + " /  .  \  |  |  |  | |  |____ |  |\  \----.|  `----.|  `--'  | |  `----.|  .  \ ")
    print(Fore.LIGHTMAGENTA_EX + "/__/ \__\ |__|  |__| |_______|| _| `._____||_______| \______/   \______||__|\__\\")
    Menu().run()

部分效果展示

单个重命名

image-20210924144633323.png

批量重命名

image-20210924144903480.png

删除

不展示了,这玩意还是自己用文件资源管理器吧,用不好删掉了,回收站里都找不到ಥ_ಥ

写出来纯粹是用来练习的

总结

这次完成这个小项目也学习到了不少

  • python利用相关库操作文件(重命名和删除)
  • 掌握了写项目的一点门道:如主函数和类的开发、相应错误的抛出(这比我上学期学java学的还更深刻,属实是Java没咋学会)
  • 新见识了ASCII的艺术签名

当然没有完全按照最初的思维导图设计那样,比如省略了判断文件和文件夹是否存在,感觉没必要了

最后修改:2021 年 10 月 25 日
如果觉得我的文章对你有用,请随意赞赏