为了账号安全,请及时绑定邮箱和手机立即绑定

使用shutil在python中复制文件

使用shutil在python中复制文件

GCT1015 2021-06-11 18:31:59
I have the following directory structure: -mailDir     -folderA         -sub1         -sub2         -inbox            -1.txt            -2.txt            -89.txt            -subInbox            -subInbox2     -folderB         -sub1         -sub2         -inbox            -1.txt            -2.txt            -200.txt            -577.txt目的是将收件箱文件夹下的所有txt文件复制到另一个文件夹中。为此,我尝试了以下代码import osfrom os import pathimport shutilrootDir = "mailDir"destDir = "destFolder"eachInboxFolderPath = []for root, dirs, files in os.walk(rootDir):    for dirName in dirs:        if(dirName=="inbox"):            eachInboxFolderPath.append(root+"\\"+dirName)for ii in eachInboxFolderPath:    for i in os.listdir(ii):        shutil.copy(path.join(ii,i),destDir)如果收件箱目录只有 .txt 文件,那么上面的代码工作正常。由于文件夹A目录下的收件箱文件夹还有其他子目录以及.txt文件,因此代码返回权限被拒绝错误。我的理解是shutil.copy 不允许复制文件夹。目的是仅将每个收件箱文件夹中的 txt 文件复制到其他位置。如果不同收件箱文件夹中的文件名相同,我必须保留两个文件名。在这种情况下,我们如何改进代码?请注意,除了 .txt 之外,所有其他文件都只是文件夹。
查看完整描述

3 回答

?
富国沪深

TA贡献1790条经验 获得超9个赞

只记得我曾经写过几个文件来解决这个确切的问题。你可以在我的 Github 上找到源代码。

简而言之,这里有两个有趣的函数:

  • list_files(loc, return_dirs=False, return_files=True, recursive=False, valid_exts=None)

  • copy_files(loc, dest, rename=False)

对于您的情况,您可以将这些函数复制并粘贴到您的项目中并copy_files像这样修改:

def copy_files(loc, dest, rename=False):

    # get files with full path

    files = list_files(loc, return_dirs=False, return_files=True, recursive=True, valid_exts=('.txt',))


    # copy files in list to dest

    for i, this_file in enumerate(files):

        # change name if renaming

        if rename:

            # replace slashes with hyphens to preserve unique name

            out_file = sub(r'^./', '', this_file)

            out_file = sub(r'\\|/', '-', out_file)

            out_file = join(dest, out_file)

            copy(this_file, out_file)

            files[i] = out_file

        else:

            copy(this_file, dest)


    return files

然后就这样称呼它:


copy_files('mailDir', 'destFolder', rename=True)

重命名方案可能不是您想要的,但至少不会覆盖您的文件。我相信这应该可以解决您的所有问题。


查看完整回答
反对 回复 2021-06-16
?
江户川乱折腾

TA贡献1851条经验 获得超5个赞

干得好:


import os

from os import path

import shutil


destDir = '<absolute-path>'

for root, dirs, files in os.walk(os.getcwd()):

    # Filter out only '.txt' files.

    files = [f for f in files if f.endswith('.txt')]

    # Filter out only 'inbox' directory.

    dirs[:] = [d for d in dirs if d == 'inbox']


for f in files:

    p = path.join(root, f)

    # print p

    shutil.copy(p, destDir)

快速而简单。


抱歉,我忘记了其中的部分,您还需要唯一的文件名。上述解决方案仅适用于单个收件箱文件夹中的不同文件名。


要从多个收件箱复制文件并在目标文件夹中具有唯一名称,您可以尝试以下操作:


import os

from os import path

import shutil


sourceDir = os.getcwd()

fixedLength = len(sourceDir)


destDir = '<absolute-path>'


filteredFiles = []


for root, dirs, files in os.walk(sourceDir):

    # Filter out only '.txt' files in all the inbox directories.

    if root.endswith('inbox'):

        # here I am joining the file name to the full path while filtering txt files

        files = [path.join(root, f) for f in files if f.endswith('.txt')]

        # add the filtered files to the main list

        filteredFiles.extend(files)


# making a tuple of file path and file name

filteredFiles = [(f, f[fixedLength+1:].replace('/', '-')) for f in filteredFiles]


for (f, n) in filteredFiles:

    print 'copying file...', f

    # copying from the path to the dest directory with specific name

    shutil.copy(f, path.join(destDir, n))


print 'copied', str(len(filteredFiles)), 'files to', destDir

如果您需要复制所有文件而不仅仅是 txt 文件,则只需将条件更改f.endswith('.txt')为os.path.isfile(f)同时过滤掉文件即可。


查看完整回答
反对 回复 2021-06-16
  • 3 回答
  • 0 关注
  • 202 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
微信客服

购课补贴
联系客服咨询优惠详情

帮助反馈 APP下载

慕课网APP
您的移动学习伙伴

公众号

扫描二维码
关注慕课网微信公众号