【问题标题】:shutil moving files keeping the same directory structureshutil 移动文件保持相同的目录结构
【发布时间】:2011-04-04 00:30:25
【问题描述】:

我想移动很多文件。这些文件的路径存储在一个列表中。我想保留整个目录结构,但想将它们移动到不同的文件夹。

例如,文件是 D:\test\test1\test1.txt D:\test\test1\test2.txt

我想将它们从 D:\ 移动到 C:\ 并保留目录结构。我该怎么做呢?

这是我的代码,它不起作用

import os, fnmatch
import shutil


f=open('test_logs.txt','r') #logs where filenames are stored with filenames as first entry

for line in f:
    filename=line.split()
    output_file="C:" + filename[0].lstrip("D:")
    shutil.move(filename[0],output_file)

我很好地读取了文件名,并且可以很好地生成目标文件名,但是当我运行它时,它给了我一个错误,说“没有这样的文件或目录”(并给出了输出文件名的路径)。

【问题讨论】:

    标签: python


    【解决方案1】:

    我想你想要这样的东西:

    import sys
    import os
    import shutil
    
    # terminology:
    # path = full path to a file, i.e. directory + file name
    # directory = directory, possibly starting with a drive
    # file name = the last component of the path
    
    sourcedrive = 'D:'
    destdrive = 'C:'
    
    log_list_file = open('test_logs.txt', 'r')
    for line in log_list_file:
        sourcepath = line.split()[0]  # XXX is this correct?
        if sourcepath.startswith(sourcedrive):
            destpath = sourcepath.replace(sourcedrive, destdrive, 1)
        else:
            print >>sys.stderr, 'Skipping %s: Not on %s' % (sourcepath, sourcedrive)
            continue
    
        destdir = os.path.dirname(destpath)    
    
        if not os.path.isdir(destdir):
            try:
                os.makedirs(destdir)
            except (OSError, IOError, Error) as e:
                print >>sys.stderr, 'Error making %s: %s' % (destdir, e)
                continue
    
        try:
            shutil.move(sourcepath, destpath)
        except (OSError, IOError, Error) as e:
            print >>sys.stderr, 'Error moving %s to %s: %s' % (sourcepath, destpath, e)
    

    如果源目录为空,是否还要删除它?

    【讨论】:

    • python2.7: 除了 (OSError, IOError, shutil.Error) as e:
    【解决方案2】:

    更新:啊,好的,我看到了问题——shutil.move 不会复制到不存在的目录。要做你想做的事,你必须首先创建新的目录树。由于使用内置移动功能比滚动您自己的复制和删除过程更安全,因此您可以这样做:

    with open('test_logs.txt','r') as f:
        files_to_copy = [line.split()[0] for line in f]
    paths_to_copy = set(os.path.split(filename)[0] for filename in files_to_copy)
    
    def ignore_files(path, names, ptc=paths_to_copy):
        return [name for name in names if os.path.join(path, name) not in ptc]
    
    shutil.copytree(src, dst, ignore=ignore_files)
    
    for filename in files_to_copy:
        output_file="C:" + filename.lstrip("D:")
        shutil.move(filename, output_file)
    

    如果这不起作用,请告诉我


    原帖:如果您只想移动部分文件,最好使用shutil.copytreeignore 关键字。假设您的文件列表包括完整路径和目录(即['D:\test\test1\test1.txt', 'D:\test\test1\test2.txt', 'D:\test\test1']),创建一个ignore_files 函数并像这样使用它:

    files_to_copy = ['D:\test\test1\test1.txt', 'D:\test\test1\test2.txt', 'D:\test\test1']
    
    def ignore_files(path, names, ftc=files_to_copy):
        return [name for name in names if os.path.join(path, name) not in ftc]
    
    shutil.copytree(src, dst, ignore=ignore_files)
    

    然后你就可以删除files_to_copy中的文件了:

    for f in files_to_copy:
        try:
            os.remove(f)
        except OSError:  # can't remove() a directory, so pass
            pass 
    

    我对此进行了测试 -- 确保包含要复制的路径以及 files_to_copy 中的文件 -- 否则,这将删除文件而不复制它们。

    【讨论】:

    • 是的,我不会移动所有文件,只是移动其中的一部分。
    • 问题是保持相同的目录结构。
    • 未移动的文件会怎样?他们只是呆在原地吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-03-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-03-30
    相关资源
    最近更新 更多