Skip to main content
 首页 » 编程设计

python之shutil.copy2之不同文件系统和伪文件的行为

2025年05月04日10exmyth

我写了一个小脚本来同步两个目录。该脚本允许同步某些文件类型,并允许通过校验和或日期进行文件比较。 比较后,应复制的文件列表将提供给使用 shutil.copy2() 模块的文件复制过程。 在各种测试运行中,我发现 shutil.copy2 有一个奇怪的行为,但我没有解决方法:

首先: 如果源是 ext3 卷而目标是 fat32(内存棒),则 shutil 会引发错误。 我认为这是因为 shutil.copy2 也尝试复制元数据,而 fat32 不支持这一点。但我不知道如何通过 try: except: 语句捕获此错误。

第二个: 第二个问题就更难了。源和目标都是 ext3 卷。在源代码中有一些完整的 Linux 目录树的备份。当我的实用程序尝试同步这些目录树时,脚本会无限循环运行,直到我的系统分区空间不足。 我试图修复此行为并在开始复制过程之前使用 stat 模块检查源文件是否为常规文件,但它无济于事。具有奇怪行为的问题文件是/proc/661/fd/3。也许还有更多,但我无法测试,因为我的系统在尝试复制此文件时因内存消耗而卡住。

我已经为这两个问题找了好几天的解决方案,希望她身边的高手程序员能够支持我。

感谢您的帮助。

这里是我的文件复制过程的代码:

def _filecopy(file_list, from_dir, to_dir, overwrt): 
print "Files and directories will be processed: " 
for file_tupel in file_list: 
    source_file_name = from_dir + file_tupel[1] + file_tupel[0] 
    try: 
        filemode = os.stat(source_file_name).st_mode 
    except: 
        filemode = 33205  
    if S_ISREG(filemode): 
        target_dir_name = to_dir + file_tupel[1] 
        if not os.path.isdir(target_dir_name): 
            print "Create directory " + target_dir_name 
            _mkdir(target_dir_name) 
        target_file_name = target_dir_name + file_tupel[0] 
        if os.path.isfile(target_file_name) and overwrt == "mark": 
            name_appendix = "_marked_by_sync_as_different_on_" + time.strftime("%a_%d_%b_%Y_%H-%M-%S", time.localtime()) 
            if target_file_name.find(".") == -1: 
                new_target_file_name = target_file_name + name_appendix 
                new_source_file_name = source_file_name + name_appendix 
            else: 
                new_target_file_prefix = target_file_name.rpartition(".")[0] 
                new_target_file_extension = target_file_name.rpartition(".")[2] 
                new_target_file_name = new_target_file_prefix + name_appendix + "." + new_target_file_extension 
                new_source_file_prefix = source_file_name.rpartition(".")[0] 
                new_source_file_name = new_source_file_prefix + name_appendix + "." + new_target_file_extension 
            print "Rename file " + target_file_name + " in " + new_target_file_name 
            os.rename(target_file_name, new_target_file_name) 
            print "Copy file " + new_target_file_name + " to " + new_source_file_name 
            try: 
                shutil.copy2(new_target_file_name, new_source_file_name) 
            except: 
                print "Could not copy " + new_target_file_name + " to " + new_source_file_name 
        print "Copy file " + source_file_name + " to " + target_file_name 
        try: 
            shutil.copy2(source_file_name, target_file_name) 
        except: 
            print "Could not copy " + source_file_name + " to " + target_file_name 
    else: 
        print source_file_name + " seems to be no regular file and will not be copied." 

按照答案 1 的提示后,shutil,copy2 语句更改为:

    shutil.copyfile(source_file_name, target_file_name) 
    try: 
        #try to set permission bits 
        shutil.copymode(new_target_file_name, new_source_file_name) 
    except: 
        print "Permission bits could not be copied" 
    try: 
        #try to copy metadata 
        shutil.copystat(new_target_file_name, new_source_file_name) 
    except: 
        print "Metadata could not be copied"   

请您参考如下方法:

shutil.copy2() 只是 shutil.copy() 后跟 shutil.copystat()。要解决您的第一个问题,您可能需要复制 source of shutil.copy2()并将 copystat() 部分包含在 try-except block 中。您应该能够从错误回溯中找出要捕获的异常。

您可能根本不想复制 /proc 文件系统。每当您调用脚本时,我都会将其排除在外。