牛骨文教育服务平台(让学习变的简单)

问题

You need to copy or move files and directories around, but you don’t want to do it bycalling out to shell commands.

解决方案

The shutil module has portable implementations of functions for copying files anddirectories. The usage is extremely straightforward. For example:

import shutil

Copy src to dst. (cp src dst)shutil.copy(src, dst)

Copy files, but preserve metadata (cp -p src dst)shutil.copy2(src, dst)

Copy directory tree (cp -R src dst)shutil.copytree(src, dst)

Move src to dst (mv src dst)shutil.move(src, dst)

The arguments to these functions are all strings supplying file or directory names. Theunderlying semantics try to emulate that of similar Unix commands, as shown in thecomments.By default, symbolic links are followed by these commands. For example, if the sourcefile is a symbolic link, then the destination file will be a copy of the file the link pointsto. If you want to copy the symbolic link instead, supply the follow_symlinks keywordargument like this:

shutil.copy2(src, dst, follow_symlinks=False)

If you want to preserve symbolic links in copied directories, do this:

shutil.copytree(src, dst, symlinks=True)

The copytree() optionally allows you to ignore certain files and directories during thecopy process. To do this, you supply an ignore function that takes a directory nameand filename listing as input, and returns a list of names to ignore as a result. For ex‐ample:

def ignore_pyc_files(dirname, filenames):return [name in filenames if name.endswith(‘.pyc")]
shutil.copytree(src, dst, ignore=ignore_pyc_files)

Since ignoring filename patterns is common, a utility function ignore_patterns() hasalready been provided to do it. For example:

shutil.copytree(src, dst, ignore=shutil.ignorepatterns(‘~","_.pyc"))

讨论

Using shutil to copy files and directories is mostly straightforward. However, onecaution concerning file metadata is that functions such as copy2() only make a besteffort in preserving this data. Basic information, such as access times, creation times,and permissions, will always be preserved, but preservation of owners, ACLs, resourceforks, and other extended file metadata may or may not work depending on the un‐derlying operating system and the user’s own access permissions. You probably wouldn’twant to use a function like shutil.copytree() to perform system backups.When working with filenames, make sure you use the functions in os.path for thegreatest portability (especially if working with both Unix and Windows). For example:

>>> filename = "/Users/guido/programs/spam.py"
>>> import os.path
>>> os.path.basename(filename)
"spam.py"
>>> os.path.dirname(filename)
"/Users/guido/programs"
>>> os.path.split(filename)
("/Users/guido/programs", "spam.py")
>>> os.path.join("/new/dir", os.path.basename(filename))
"/new/dir/spam.py"
>>> os.path.expanduser("~/guido/programs/spam.py")
"/Users/guido/programs/spam.py"
>>>

One tricky bit about copying directories with copytree() is the handling of errors. Forexample, in the process of copying, the function might encounter broken symbolic links,files that can’t be accessed due to permission problems, and so on. To deal with this, allexceptions encountered are collected into a list and grouped into a single exception thatgets raised at the end of the operation. Here is how you would handle it:

try:shutil.copytree(src, dst)except shutil.Error as e:for src, dst, msg in e.args[0]:# src is source name# dst is destination name# msg is error message from exceptionprint(dst, src, msg)
If you supply the ignore_dangling_symlinks=True keyword argument, then copytree() will ignore dangling symlinks.The functions shown in this recipe are probably the most commonly used. However,shutil has many more operations related to copying data. The documentation is def‐initely worth a further look. See the Python documentation.