zoukankan      html  css  js  c++  java
  • 文件查询之三:文件和目录的批量操作

    经过之前两篇的随笔已经可以将所需要的文件和目录查找出来,并且保存在一个文档中,所以现在就是利用保存文件或目录的文档来进行批量处理,对文件或目录进行批量的

    删除、复制和移动。主要是用到shutil模块中的函数和os模块中的函数进行一系列的操作。shutil模块存在大量的文件操作和目录操作的函数,包括常用的移动文件或复制文件

    等操作,其中os和shutil下对于函数的功能存在交集,只不过相同功能下的函数名存在差异,函数上的细节处理方面也有可能不一样。在这里主要的是讲shutil模块下的函数。

    首先是将文件的操作函数写下,由于两个功能具体的实现是差不多的,而且只需要改写一下函数名就可以实现另一个文件操作的功能,所有这里使用了一个字典来标识函数,

    然后通过相应的功能函数去调用,并且传入相应的字典值来调用shutil模块下的函数,具体代码如下:

    FileFunc = {'copyFile':shutil.copy2,
                'moveFile':shutil.move}
    
    def OperationFileFunc(srcPath,dstPath,FileFunc):
        if os.path.exists(srcPath):
            # 该文件存在于源目录
            if os.path.exists(dstPath + '\' +srcPath.split('\')[-1]):
                print('The file is exists in %s' % dstPath)
                # y:yes  覆盖  n:no 创建一个副本   i:ignore 不复制
                result = raw_input('Do you want to continue cover it?(y/n/i):')
                if result in ['y','Y']:
                    # 覆盖原有文件
                    FileFunc(srcPath,dstPath)
                elif result in ['n','N']:
                    # 创建副本
                    fname = srcPath.split('\')[-1].split('.')
                    FileFunc(srcPath,dstPath+'\'+fname[0]+'bak.'+fname[1])
                else:
                    # 不操作
                    print('[+] No copy file : %s' % srcPath)
            else:
                # 当目标目录下不存在该文件时,就直接进行相应的操作
                FileFunc(srcPath,dstPath)
        else:
            print('[+] the source path : %s is not exists or not a effective file path' % srcPath)

    如上可以看到,字典FileFunc保存了两个函数,一个是复制文件的函数和一个是移动文件的函数。因为两个函数的实现过程是相似的,所以为了简洁代码,代码只需要写一遍就

    可以了,然后就通过传入不同的字典值来对函数的控制,进行对文件不同的操作。对于文件复制的函数,使用copy2函数的是因为该函数会将源文件下的一些元数据也会复制到

    新的目标文件中。元数据主要有文件的权限、修改时间、访问时间和文件所有者等,但是创建时间是不会复制到新的文件中的,新的文件将使用新的创建时间。如果你想要只是

    仅仅将文件内容复制而已,那么就可以使用copyfile函数来复制文件。在这里你还可以使用copy函数来操作,只不过copy2函数对文件的操作相当于copy函数加上stat函数的

    总和,所以在本文就使用这个copy2函数进行操作,如果有不同的需求,可以自行实现。在这个函数中首先是先判断文件是否存在于源目录和目标目录,当文件存在于目标目录时,

    则将文件进行覆盖、备份或不复制操作,这个在操作的过程中可以自行输入或将 result = raw_input('Do you want to continue cover it?(y/n/i):') 的值变为固定的值,比如:

    改为result='n',这样就是当目标目录中存在相同文件名的文件时,会自动将其保存为文件副本,以免原有的文件的数据丢失。这样更符合批量处理,因为在处理大量的文件中,

    如果还要人工去操作,这无疑是不允许的,因为这样的情况下操作是会使人容易操作出错的,所以还是将其改为自己想要的效果就可以了。

    然后就是目录下的文件以及子目录的移动和复制,至于文件的删除和目录的删除在后面再一一细说。详细代码如下:

    DirectoryFunc = {'copytree':shutil.copytree,
                     'move':shutil.move}
    def OperationDirectoryFunc(srcPath,dstPath,DirectoryFunc):
        # 初始化线程
        t = threading.Thread(target=DirectoryFunc,args=(srcPath,dstPath))
        # srcPath 必须存在而且是一个目录
        if os.path.exists(srcPath) and os.path.isdir(srcPath):
            if not os.path.exists(dstPath):
                # 因为dstPath必须要不存在,所以应该判断其是否存在
                t.start()
            else:
                print('the destination : %s is exists,but it must not exists.' % dstPath)
                print('please uses another directory')
        else:
            print('[+] the source path : %s is not exists or not a effective directory' % srcPath)
        # 等待所有的线程都完成才退出
        if t.isAlive():
            t.join()

    这个函数的操作和上面的文件函数基本一样,就不一一细说了,主要是用到的函数不一样。因为我觉得目录存在的文件比较多,所以加进了多线程来处理目录下的文件及目录。

    这个函数需要注意的是:copytree函数的两个传进参数都必须是目录,不能是文件,如果是文件,则会抛出相应的异常,你也可以通过捕获异常的处理方式来判断传入的是否为

    目录,然后进行目录和文件的不同操作。为了保证线程完全执行成功,t.join()是等待线程结束后才结束整个程序,而这个t.isAlive()判断该线程是否是运行状态,因为只有线程

    运行才可以执行t.join(),不然会出错。因为当输入的路径不是目录时,就会导致线程不会执行了,所以这个判断语句是一定要使用的。而且这个t.join()语句不能放在t.start()

    后面,这样就会导致程序停在这里,使在t.join()语句下的其他语句不能执行,直到线程执行完才可以执行下一个语句。

    那么下面就是删除文件和删除目录下的所有文件和目录的操作,具体代码如下:

    # 删除文件  os.remove()
    def deleteFile(srcPath):
        if os.path.exists(srcPath) and os.path.isfile(srcPath):
            os.remove(srcPath)
        else:
            print('the file : %s is not exists or not a effective file path' % srcPath)
    
    
    # 删除整个目录下的文件和目录  shutil.rmtree()
    def deleteDirectory(srcPath):if os.path.exists(srcPath) and os.path.isdir(srcPath):
            shutil.rmtree(srcPath)
        else:
            print('[+] the source path : %s is not exists or not a effective directory' % srcPath)

    在这里就是使用了shutil模块下的rmtree函数进行删除目录和os模块下的remove函数来删除文件。因为这两个函数执行的流程都是类似的,所以你也可以使用上述的字典方式

    来调用函数。这rmtree()和remove()对输入的参数都是有要求的,所以在接收参数前要进行判断是否符合,以免函数执行出错导致程序停止工作。

    最后就是调用上述的功能函数来对文件或目录进行操作,具体的代码如下:

    # 复制文件
    def copyFile(srcPath,dstPath):
        OperationFileFunc(srcPath,dstPath,FileFunc['copyFile'])
    
    # 移动文件
    def moveFile(srcPath,dstPath):
        OperationFileFunc(srcPath,dstPath,FileFunc['moveFile'])
    
    # 复制整个目录下的文件的和目录
    def copyDirectory(srcPath,dstPath,DirectoryFunc=DirectoryFunc['copytree']):
        OperationDirectoryFunc(srcPath,dstPath,DirectoryFunc)
    
    # 移动整个目录下的文件和目录
    def moveDirectory(srcPath,dstPath,DirectoryFunc=DirectoryFunc['move']):
        OperationDirectoryFunc(srcPath,dstPath,DirectoryFunc)

    在这些调用函数中并没有过多的操作,只是简单的对相应的操作函数进行调用,但是如果你有想到其他的操作也可以将该函数修改,增加一些有条件限制的进行复制或移动等其他

    想要的操作,比如:只对相应大小的文件进行复制等操作,或者只对相应时间段的文件进行操作等等。虽然我的原意是从文件中读取相应的文件或目录路径进行操作,但是你也可

    以将其嵌入在前两篇的文件查询代码中,进行一连贯的文件操作流程,达到自动化管理文件的目的。但是这些代码是有缺陷的或者是不完整的,在程序中没有使用多线程来进行操

    作,所以容易遇到速度上的瓶颈,在操作的数量大时,就会导致花费的时间过久。在这里就不再给出其调用函数的测试代码了,这些都是简单的打开文件进行遍历的结果,然后就

    是对每个路径进行遍历,并进行一一操作。在这里奉劝大家一句,数据是宝贵的,所以在这类测试前,先将数据进行备份,以免造成不可收拾的后果。

    http://www.cnblogs.com/GHost-Ma/
  • 相关阅读:
    ubuntu安装jdk的两种方法
    LeetCode 606. Construct String from Binary Tree (建立一个二叉树的string)
    LeetCode 617. Merge Two Binary Tree (合并两个二叉树)
    LeetCode 476. Number Complement (数的补数)
    LeetCode 575. Distribute Candies (发糖果)
    LeetCode 461. Hamming Distance (汉明距离)
    LeetCode 405. Convert a Number to Hexadecimal (把一个数转化为16进制)
    LeetCode 594. Longest Harmonious Subsequence (最长的协调子序列)
    LeetCode 371. Sum of Two Integers (两数之和)
    LeetCode 342. Power of Four (4的次方)
  • 原文地址:https://www.cnblogs.com/GHost-Ma/p/5595375.html
Copyright © 2011-2022 走看看