如果文件不存在,则复制文件

20

我对Python比较新,想知道如何在复制文件到另一个位置之前,先检查该文件是否已存在于目标文件夹中?

我想要检查文件是否存在的原因是,该脚本将被放置在任务计划程序中并按照预定计划运行,因此我不想每次都复制所有文件,只需复制目标文件夹中不存在的文件即可。

提前感谢您!


os.path.exists(/some/path/) - yuvi
就我个人而言,我认为几乎总有比“os.path.exists”更好的处理文件创建/删除/使用的方法。在大多数情况下,有另一个模块可以更优雅地处理它(就像我在我的答案中使用glob来比较两个列表),如果没有,那么try/catch可以更好地防止竞争条件。我想不出任何一个我编写的脚本使用“os.path.exists”,我不能重写以使用具有更好功能的“glob”。 - Adam Smith
@adsmith,除非您有安全方面的顾虑,否则没有理由不使用os.path.exist - yuvi
使用rsync代替cp。 - Neo li
2个回答

11
import glob
import os.path
import shutil

SRC_DIR = #your source directory
TARG_DIR = #your target directory

GLOB_PARMS = "*" #maybe "*.pdf" ?

for file in glob.glob(os.path.join(SRC_DIR, GLOB_PARMS)):
    if file not in glob.glob(os.path.join(TARG_DIR, GLOB_PARMS)):
        shutil.copy(file,TARG_DIR)
    else:
        print("{} exists in {}".format(
            file,os.path.join(os.path.split(TARG_DIR)[-2:])))
        # This is just a print command that outputs to console that the
        # file was already in directory

我假设您试图使用这个命令发送整个文件夹,否则 glob 使用的是非常易于理解的接口。 glob.glob("*.txt") 将抓取所有 .txt 扩展名的文件等等。调整它以符合您的要求不应该太难。

需要注意的是,文件复制通常涉及竞争条件。基本上,在检查文件是否不在 TARG_DIR (if file not in glob.glob(TARG_DIR)) 并将其实际复制到那里 (shutil.copy(file,TARG_DIR)) 之间会有时间流逝。在这段时间内,文件可能会出现在那里,这将导致 shutil.copy 覆盖该文件。如果这不是您想要的功能,那么您应该考虑使用其他方法。我不知道有没有一个好方法可以尝试复制文件,但如果该文件已经存在,则返回异常。

正如另一个答案提到的那样,Try/Except 块在这里也可能很有用,如果在运行脚本时可能没有写入目录的访问权限。如果是这种情况,shutil.copy 将返回一个 IOError 异常。我相信如果您没有读取源目录的访问权限(反过来将通过 "For" 循环不传递任何内容,因此您不会有任何错误),则 glob 将只返回一个空列表。

编辑:显然 glob 的工作方式与我记得的不同,对此感到抱歉。


1
在这种情况下,我不想复制整个文件夹,我想复制文件夹内的内容,即PDF文件。 - mpboyle
1
这就是它的作用 - 抱歉我表达不清。glob.glob 根据您提供的一些参数返回文件夹内容的列表(例如,glob.glob(TARG_DIR+"\\*.pdf") 将返回 TARG_DIR 中扩展名为 PDF 的文件列表)。 - Adam Smith
第10行是 shutil.copy(file,TARG_DIR)。我需要指定文件类型(.pdf)吗? - mpboyle
不行。你能把堆栈跟踪粘贴给我吗? - Adam Smith
Traceback (most recent call last): File "C:\Users\mboyle\Desktop\CopyPaste.py", line 10, in <module> shutil.copy(file,TARG_DIR) File "C:\Python27\ArcGIS10.1\lib\shutil.py", line 116, in copy copyfile(src, dst) File "C:\Python27\ArcGIS10.1\lib\shutil.py", line 81, in copyfile with open(src, 'rb') as fsrc: IOError: [Errno 13] Permission denied: 'C:\\Users\\mboyle\\Documents\\Source' - mpboyle
显示剩余8条评论

-1
在Python中,运行代码时经常会遇到错误,称为“异常”。因此,我们使用了“try/catch”语句块来处理这些异常。
以下是我日常使用的一段代码片段,用于从目录中清除文件,如果文件不存在则跳过。
def DeleteFile(Path_):
    """Deletes saved project AND its corresponding "files" folder."""
    try: #deletes the folder
        os.remove(Path_)
    except OSError:
        pass
    try: #deletes the file, using some fancy python operations to arrive at the filename
        shutil.rmtree(os.path.join(os.path.dirname(Path_),os.path.splitext(os.path.basename(Path_))[0])+"_files", True)
    except OSError:
        pass

这是一个检查文件是否存在的经典示例。在您的try语句中,您可以尝试复制文件而不是删除它。如果失败,则继续执行pass,它只会跳过try/catch块。

请注意,try/catch可用于捕获任何异常,也可以用于捕获特定的异常。我已经写入了OSError,但请仔细阅读以确保这是您想要的异常类型。如果您在catch中有一个特定的错误,并且系统返回了错误类型不正确的错误,则您的try/catch将无法按照您想要的方式工作。所以,请确保选择最好的情况下是通用的。

编码愉快!

编辑:值得注意的是,这个try/catch系统是一种非常Pythonic的方法。 try/catch非常简单和流行,但您的情况可能需要其他方法。

编辑:我不确定是否值得注意,但我意识到我的答案并没有直接告诉你如何检查文件是否存在。相反,它假设文件不存在并继续进行操作。如果遇到问题(即它存在且您需要覆盖),您可以使其自动跳过整个内容并转到下一个内容。同样,这只是完成相同任务的许多方法之一。


在大多数Python项目中,函数和变量名中的大写字母被认为是不好的风格:https://www.python.org/dev/peps/pep-0008/ - karlson

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接