利用Python做一个复制目录的程序>_(Python编程 | 系统编程 | 完整的系统程序 | 复制目录树)

我要学习

《Python编程》笔记专栏现以开源到Gitee,其中包含我编写的示例程序文件和官方示例程序文件,以及md形式的笔记,欢迎各位给个Star。

文章目录

复制目录树

示例:cpall.py

#!/usr/bin/env python
"""
##############################################################################
用法:“./cpall.py dirFrom dirTo [-m maxFileLoad] [-b blockSize] [-v verbose]”。

递归地复制dirFrom到dirTo下。和Unix命令“cp -r dirFrom dirTo”效果类似,其中假定dirFrom
和dirTo都是目录。
##############################################################################
"""

import os
import sys
import time

MAXFILELOAD = 1024 * 1024
BLOCKSIZE = 1024 * 1024
VERBOSE = 0


def copyFile(
    pathFrom,
    pathTo,
    maxFileLoad=MAXFILELOAD,
    blockSize=BLOCKSIZE
):
    """
    将单个文件逐字节的从pathFrom复制到pathTo。
    使用二进制文件模式防止Unicode解码及换行符转换。
    """

    if os.path.getsize(pathFrom) <= maxFileLoad:
        open(pathTo, 'wb').write(open(pathFrom, 'rb').read())
    else:
        fileFrom = open(pathFrom, 'rb')
        fileTo = open(pathTo, 'wb')
        while True:
            bytesFrom = fileFrom.read(blockSize)
            if not bytesFrom:
                break
            fileTo.write(bytesFrom)
        fileFrom.close()
        fileTo.close()


def copyTree(
    dirFrom,
    dirTo,
    maxFileLoad=MAXFILELOAD,
    blockSize=BLOCKSIZE,
    verbose=VERBOSE
):
    """
    将dirFrom下的内容递归地复制到dirTo,返回(文件数目,目录数目)形式的元组。
    为避免在某些平台上目录吗不可解码,可能需要为其名使用字节。
    """

    fileCount = dirCount = 0

    for filename in os.listdir(dirFrom):
        pathFrom = os.path.join(dirFrom, filename)
        pathTo = os.path.join(dirTo, filename)

        if not os.path.isdir(pathFrom):
            try:
                # print('verbose ->', verbose)
                if verbose > 1:
                    print('文件:正在将{}复制到{}'.format(pathFrom, pathTo))
                copyFile(pathFrom, pathTo, maxFileLoad, blockSize)
                fileCount += 1
            except Exception:
                print('错误:将{}复制到{},已跳过'.format(pathFrom, pathTo))
                print(sys.exc_info()[0], sys.exc_info()[1])

        else:
            if verbose:
                print('目录:正在将{}复制到{}'.format(pathFrom, pathTo))
            try:
                os.mkdir(pathTo)
            except Exception:
                print('错误:创建{},已跳过'.format(pathTo))
                print(sys.exc_info()[0], sys.exc_info()[1])
            below = copyTree(pathFrom, pathTo, maxFileLoad, blockSize, verbose)
            fileCount += below[0]
            dirCount += below[1]
            dirCount += 1

    return fileCount, dirCount


def getInt(label, var):
    index = sys.argv.index(label) + 1

    try:
        var = int(sys.argv[index])
    except IndexError:
        print('错误:命令行参数{}之后无数字')
        sys.exit()
    except ValueError:
        print('错误:命令行参数{}之后不是数字')
        sys.exit()
    else:
        return var


def getArgs(
    maxFileLoad=MAXFILELOAD,
    blockSize=BLOCKSIZE,
    verbose=VERBOSE
):
    """
    获取并验证文件命令行参数
    """
    if len(sys.argv) < 3:
        msg = '使用方法:'
        msg += '\n./cpall.py dirFrom dirTo '
        msg += '[-m maxFileLoad] [-b blockSize] [-v verbose]'
        print(msg)
        sys.exit()

    dirFrom, dirTo = sys.argv[1:3]
    dirFrom, dirTo = map(os.path.abspath, [dirFrom, dirTo])

    if not os.path.isdir(dirFrom):
        print('错误:dirFrom不是一个目录')
        sys.exit()

    if os.path.isfile(dirTo):
        print('错误:dirTo不是一个目录')
        sys.exit()

    dirTo = os.path.join(dirTo, os.path.basename(dirFrom))

    if not os.path.exists(dirTo):
        os.mkdir(dirTo)
        print('提示:创建了dirTo')
    else:
        print('警告:dirTo已存在')

    if hasattr(os.path, 'samefile'):
        isSame = os.path.samefile(dirFrom, dirTo)
    else:
        isSame = os.path.abspath(dirFrom) == os.path.abspath(dirTo)

    if isSame:
        print('错误:dirFrom和dirTo是同一个目录')
        sys.exit()

    if '-m' in sys.argv:
        maxFileLoad = getInt('-m', maxFileLoad)
    if '-b' in sys.argv:
        blockSize = getInt('-b', blockSize)
    if '-v' in sys.argv:
        verbose = getInt('-v', verbose)

    return dirFrom, dirTo, maxFileLoad, blockSize, verbose


def command():
    args = getArgs()
    print('参数:')
    names = ('dirFrom', 'dirTo', 'maxFileLoad', 'blockSize', 'verbose')
    for index in range(len(names)):
        print('\t{} -> {}'.format(names[index], args[index]))
    print('正在复制')
    start = time.time()
    fcount, dcount = copyTree(*args)
    finish = time.time()
    print('复制完成:用时{}s,共复制了{}个文件、{}个目录'.format(finish - start, fcount, dcount))


if __name__ == '__main__':
    command()

运行:cpall.py

$ ./cpall.py ../../ /media/beacherhou/Git仓库/ -v 1 -m 1024 -b 1024
提示:创建了dirTo
正在复制
目录:正在将/media/beacherhou/Git仓库/python-programming---markdown-notes/my_PP4E/system复制到/media/beacherhou/Git仓库/my_PP4E/system
目录:正在将/media/beacherhou/Git仓库/python-programming---markdown-notes/my_PP4E/system/filetools复制到/media/beacherhou/Git仓库/my_PP4E/system/filetools
目录:正在将/media/beacherhou/Git仓库/python-programming---markdown-notes/my_PP4E/system/filetools/tester复制到/media/beacherhou/Git仓库/my_PP4E/system/filetools/tester
目录:正在将/media/beacherhou/Git仓库/python-programming---markdown-notes/my_PP4E/system/filetools/tester/Args复制到/media/beacherhou/Git仓库/my_PP4E/system/filetools/tester/Args
目录:正在将/media/beacherhou/Git仓库/python-programming---markdown-notes/my_PP4E/system/filetools/tester/Inputs复制到/media/beacherhou/Git仓库/my_PP4E/system/filetools/tester/Inputs
目录:正在将/media/beacherhou/Git仓库/python-programming---markdown-notes/my_PP4E/system/filetools/tester/Scripts复制到/media/beacherhou/Git仓库/my_PP4E/system/filetools/tester/Scripts
目录:正在将/media/beacherhou/Git仓库/python-programming---markdown-notes/my_PP4E/system/__pycache__复制到/media/beacherhou/Git仓库/my_PP4E/system/__pycache__
复制完成:用时0.21999740600585938s,共复制了103个文件、7个目录

———————————————————————————————————————————

😃 学完博客后,是不是有所启发呢?如果对此还有疑问,欢迎在评论区留言哦。
如果还想了解更多的信息,欢迎大佬们关注我哦,也可以查看我的个人博客网站BeacherHou

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

RizzoHou

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值