blob: 78504b9d3fb3b9e4cde4fdeebe6a025cfc7085e0 [file] [log] [blame]
Guido van Rossume7b146f2000-02-04 15:28:42 +00001"""Utility functions for copying files and directory trees.
Guido van Rossum9d0a3df1997-04-29 14:45:19 +00002
Guido van Rossum959fa011999-08-18 20:03:17 +00003XXX The functions here don't copy the resource fork or other metadata on Mac.
Guido van Rossum9d0a3df1997-04-29 14:45:19 +00004
5"""
Guido van Rossumc6360141990-10-13 19:23:40 +00006
Guido van Rossumc96207a1992-03-31 18:55:40 +00007import os
Guido van Rossum83c03e21999-02-23 23:07:51 +00008import sys
Guido van Rossum9d0a3df1997-04-29 14:45:19 +00009import stat
Brett Cannon1c3fa182004-06-19 21:11:35 +000010from os.path import abspath
Georg Brandl2ee470f2008-07-16 12:55:28 +000011import fnmatch
Antoine Pitrou9f274b12010-03-22 20:12:40 +000012import errno
Guido van Rossumc6360141990-10-13 19:23:40 +000013
Skip Montanaro0de65802001-02-15 22:15:14 +000014__all__ = ["copyfileobj","copyfile","copymode","copystat","copy","copy2",
Antoine Pitrou7fff0962009-05-01 21:09:44 +000015 "copytree","move","rmtree","Error", "SpecialFileError"]
Martin v. Löwise9ce0b02002-10-07 13:23:24 +000016
Neal Norwitz4ce69a52005-09-01 00:45:28 +000017class Error(EnvironmentError):
Martin v. Löwise9ce0b02002-10-07 13:23:24 +000018 pass
Guido van Rossumc6360141990-10-13 19:23:40 +000019
Antoine Pitrou7fff0962009-05-01 21:09:44 +000020class SpecialFileError(EnvironmentError):
21 """Raised when trying to do a kind of operation (e.g. copying) which is
22 not supported on a special file (e.g. a named pipe)"""
23
Georg Brandl6aa2d1f2008-08-12 08:35:52 +000024try:
25 WindowsError
26except NameError:
27 WindowsError = None
28
Greg Stein42bb8b32000-07-12 09:55:30 +000029def copyfileobj(fsrc, fdst, length=16*1024):
30 """copy data from file-like object fsrc to file-like object fdst"""
31 while 1:
32 buf = fsrc.read(length)
33 if not buf:
34 break
35 fdst.write(buf)
36
Johannes Gijsbers46f14592004-08-14 13:30:02 +000037def _samefile(src, dst):
38 # Macintosh, Unix.
39 if hasattr(os.path,'samefile'):
Johannes Gijsbersf9a098e2004-08-14 14:51:01 +000040 try:
41 return os.path.samefile(src, dst)
42 except OSError:
43 return False
Johannes Gijsbers46f14592004-08-14 13:30:02 +000044
45 # All other platforms: check for same pathname.
46 return (os.path.normcase(os.path.abspath(src)) ==
47 os.path.normcase(os.path.abspath(dst)))
Tim Peters495ad3c2001-01-15 01:36:40 +000048
Guido van Rossumc6360141990-10-13 19:23:40 +000049def copyfile(src, dst):
Guido van Rossum9d0a3df1997-04-29 14:45:19 +000050 """Copy data from src to dst"""
Johannes Gijsbers46f14592004-08-14 13:30:02 +000051 if _samefile(src, dst):
Collin Winterce36ad82007-08-30 01:19:48 +000052 raise Error("`%s` and `%s` are the same file" % (src, dst))
Johannes Gijsbers46f14592004-08-14 13:30:02 +000053
Guido van Rossuma2baf461997-04-29 14:06:46 +000054 fsrc = None
55 fdst = None
Antoine Pitrou7fff0962009-05-01 21:09:44 +000056 for fn in [src, dst]:
57 try:
58 st = os.stat(fn)
59 except OSError:
60 # File most likely does not exist
61 pass
Benjamin Petersonc0d98aa2009-06-05 19:13:27 +000062 else:
63 # XXX What about other special files? (sockets, devices...)
64 if stat.S_ISFIFO(st.st_mode):
65 raise SpecialFileError("`%s` is a named pipe" % fn)
Guido van Rossuma2baf461997-04-29 14:06:46 +000066 try:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +000067 fsrc = open(src, 'rb')
68 fdst = open(dst, 'wb')
Greg Stein42bb8b32000-07-12 09:55:30 +000069 copyfileobj(fsrc, fdst)
Guido van Rossuma2baf461997-04-29 14:06:46 +000070 finally:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +000071 if fdst:
72 fdst.close()
73 if fsrc:
74 fsrc.close()
Guido van Rossumc6360141990-10-13 19:23:40 +000075
Guido van Rossumc6360141990-10-13 19:23:40 +000076def copymode(src, dst):
Guido van Rossum9d0a3df1997-04-29 14:45:19 +000077 """Copy mode bits from src to dst"""
Tim Peters0c947242001-01-21 20:00:00 +000078 if hasattr(os, 'chmod'):
79 st = os.stat(src)
Walter Dörwald294bbf32002-06-06 09:48:13 +000080 mode = stat.S_IMODE(st.st_mode)
Tim Peters0c947242001-01-21 20:00:00 +000081 os.chmod(dst, mode)
Guido van Rossumc6360141990-10-13 19:23:40 +000082
Guido van Rossumc6360141990-10-13 19:23:40 +000083def copystat(src, dst):
Thomas Wouterscf297e42007-02-23 15:07:44 +000084 """Copy all stat info (mode bits, atime, mtime, flags) from src to dst"""
Guido van Rossuma2baf461997-04-29 14:06:46 +000085 st = os.stat(src)
Walter Dörwald294bbf32002-06-06 09:48:13 +000086 mode = stat.S_IMODE(st.st_mode)
Tim Peters0c947242001-01-21 20:00:00 +000087 if hasattr(os, 'utime'):
Walter Dörwald294bbf32002-06-06 09:48:13 +000088 os.utime(dst, (st.st_atime, st.st_mtime))
Tim Peters0c947242001-01-21 20:00:00 +000089 if hasattr(os, 'chmod'):
90 os.chmod(dst, mode)
Thomas Wouterscf297e42007-02-23 15:07:44 +000091 if hasattr(os, 'chflags') and hasattr(st, 'st_flags'):
Antoine Pitrou9f274b12010-03-22 20:12:40 +000092 try:
93 os.chflags(dst, st.st_flags)
94 except OSError as why:
95 if not hasattr(errno, 'EOPNOTSUPP') or why.errno != errno.EOPNOTSUPP:
96 raise
Guido van Rossum9d0a3df1997-04-29 14:45:19 +000097
Guido van Rossumc6360141990-10-13 19:23:40 +000098def copy(src, dst):
Guido van Rossum9d0a3df1997-04-29 14:45:19 +000099 """Copy data and mode bits ("cp src dst").
Tim Peters495ad3c2001-01-15 01:36:40 +0000100
Guido van Rossum9d0a3df1997-04-29 14:45:19 +0000101 The destination may be a directory.
102
103 """
Guido van Rossuma2baf461997-04-29 14:06:46 +0000104 if os.path.isdir(dst):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000105 dst = os.path.join(dst, os.path.basename(src))
Guido van Rossuma2baf461997-04-29 14:06:46 +0000106 copyfile(src, dst)
107 copymode(src, dst)
Guido van Rossumc6360141990-10-13 19:23:40 +0000108
Guido van Rossumc6360141990-10-13 19:23:40 +0000109def copy2(src, dst):
Guido van Rossum9d0a3df1997-04-29 14:45:19 +0000110 """Copy data and all stat info ("cp -p src dst").
111
112 The destination may be a directory.
113
114 """
Guido van Rossuma2baf461997-04-29 14:06:46 +0000115 if os.path.isdir(dst):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000116 dst = os.path.join(dst, os.path.basename(src))
Guido van Rossuma2baf461997-04-29 14:06:46 +0000117 copyfile(src, dst)
118 copystat(src, dst)
Guido van Rossumc6360141990-10-13 19:23:40 +0000119
Georg Brandl2ee470f2008-07-16 12:55:28 +0000120def ignore_patterns(*patterns):
121 """Function that can be used as copytree() ignore parameter.
Guido van Rossum9d0a3df1997-04-29 14:45:19 +0000122
Georg Brandl2ee470f2008-07-16 12:55:28 +0000123 Patterns is a sequence of glob-style patterns
124 that are used to exclude files"""
125 def _ignore_patterns(path, names):
126 ignored_names = []
127 for pattern in patterns:
128 ignored_names.extend(fnmatch.filter(names, pattern))
129 return set(ignored_names)
130 return _ignore_patterns
131
132def copytree(src, dst, symlinks=False, ignore=None):
Guido van Rossum9d0a3df1997-04-29 14:45:19 +0000133 """Recursively copy a directory tree using copy2().
134
135 The destination directory must not already exist.
Neal Norwitza4c93b62003-02-23 21:36:32 +0000136 If exception(s) occur, an Error is raised with a list of reasons.
Guido van Rossum9d0a3df1997-04-29 14:45:19 +0000137
138 If the optional symlinks flag is true, symbolic links in the
139 source tree result in symbolic links in the destination tree; if
140 it is false, the contents of the files pointed to by symbolic
141 links are copied.
142
Georg Brandl2ee470f2008-07-16 12:55:28 +0000143 The optional ignore argument is a callable. If given, it
144 is called with the `src` parameter, which is the directory
145 being visited by copytree(), and `names` which is the list of
146 `src` contents, as returned by os.listdir():
147
148 callable(src, names) -> ignored_names
149
150 Since copytree() is called recursively, the callable will be
151 called once for each directory that is copied. It returns a
152 list of names relative to the `src` directory that should
153 not be copied.
154
Guido van Rossum9d0a3df1997-04-29 14:45:19 +0000155 XXX Consider this example code rather than the ultimate tool.
156
157 """
Guido van Rossuma2baf461997-04-29 14:06:46 +0000158 names = os.listdir(src)
Georg Brandl2ee470f2008-07-16 12:55:28 +0000159 if ignore is not None:
160 ignored_names = ignore(src, names)
161 else:
162 ignored_names = set()
163
Johannes Gijsberse4172ea2005-01-08 12:31:29 +0000164 os.makedirs(dst)
Martin v. Löwise9ce0b02002-10-07 13:23:24 +0000165 errors = []
Guido van Rossuma2baf461997-04-29 14:06:46 +0000166 for name in names:
Georg Brandl2ee470f2008-07-16 12:55:28 +0000167 if name in ignored_names:
168 continue
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000169 srcname = os.path.join(src, name)
170 dstname = os.path.join(dst, name)
171 try:
172 if symlinks and os.path.islink(srcname):
173 linkto = os.readlink(srcname)
174 os.symlink(linkto, dstname)
175 elif os.path.isdir(srcname):
Georg Brandl2ee470f2008-07-16 12:55:28 +0000176 copytree(srcname, dstname, symlinks, ignore)
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000177 else:
Antoine Pitrou7fff0962009-05-01 21:09:44 +0000178 # Will raise a SpecialFileError for unsupported file types
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000179 copy2(srcname, dstname)
Georg Brandla1be88e2005-08-31 22:48:45 +0000180 # catch the Error from the recursive copytree so that we can
181 # continue with other files
Guido van Rossumb940e112007-01-10 16:19:56 +0000182 except Error as err:
Georg Brandla1be88e2005-08-31 22:48:45 +0000183 errors.extend(err.args[0])
Antoine Pitrou7fff0962009-05-01 21:09:44 +0000184 except EnvironmentError as why:
185 errors.append((srcname, dstname, str(why)))
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000186 try:
187 copystat(src, dst)
Guido van Rossumb940e112007-01-10 16:19:56 +0000188 except OSError as why:
Georg Brandl6aa2d1f2008-08-12 08:35:52 +0000189 if WindowsError is not None and isinstance(why, WindowsError):
190 # Copying file access times may fail on Windows
191 pass
192 else:
193 errors.extend((src, dst, str(why)))
Martin v. Löwise9ce0b02002-10-07 13:23:24 +0000194 if errors:
Collin Winterce36ad82007-08-30 01:19:48 +0000195 raise Error(errors)
Guido van Rossumd7673291998-02-06 21:38:09 +0000196
Barry Warsaw234d9a92003-01-24 17:36:15 +0000197def rmtree(path, ignore_errors=False, onerror=None):
Guido van Rossumd7673291998-02-06 21:38:09 +0000198 """Recursively delete a directory tree.
199
Johannes Gijsbersef5ffc42004-10-31 12:05:31 +0000200 If ignore_errors is set, errors are ignored; otherwise, if onerror
201 is set, it is called to handle the error with arguments (func,
202 path, exc_info) where func is os.listdir, os.remove, or os.rmdir;
203 path is the argument to that function that caused it to fail; and
204 exc_info is a tuple returned by sys.exc_info(). If ignore_errors
205 is false and onerror is None, an exception is raised.
206
Guido van Rossumd7673291998-02-06 21:38:09 +0000207 """
Johannes Gijsbersef5ffc42004-10-31 12:05:31 +0000208 if ignore_errors:
209 def onerror(*args):
Barry Warsaw234d9a92003-01-24 17:36:15 +0000210 pass
Johannes Gijsbersef5ffc42004-10-31 12:05:31 +0000211 elif onerror is None:
212 def onerror(*args):
213 raise
Christian Heimes9bd667a2008-01-20 15:14:11 +0000214 try:
215 if os.path.islink(path):
216 # symlinks to directories are forbidden, see bug #1669
217 raise OSError("Cannot call rmtree on a symbolic link")
218 except OSError:
219 onerror(os.path.islink, path, sys.exc_info())
220 # can't continue even if onerror hook returns
221 return
Johannes Gijsbersef5ffc42004-10-31 12:05:31 +0000222 names = []
223 try:
224 names = os.listdir(path)
Guido van Rossumb940e112007-01-10 16:19:56 +0000225 except os.error as err:
Johannes Gijsbersef5ffc42004-10-31 12:05:31 +0000226 onerror(os.listdir, path, sys.exc_info())
227 for name in names:
228 fullname = os.path.join(path, name)
229 try:
230 mode = os.lstat(fullname).st_mode
231 except os.error:
232 mode = 0
233 if stat.S_ISDIR(mode):
234 rmtree(fullname, ignore_errors, onerror)
Barry Warsaw234d9a92003-01-24 17:36:15 +0000235 else:
Johannes Gijsbersef5ffc42004-10-31 12:05:31 +0000236 try:
237 os.remove(fullname)
Guido van Rossumb940e112007-01-10 16:19:56 +0000238 except os.error as err:
Johannes Gijsbersef5ffc42004-10-31 12:05:31 +0000239 onerror(os.remove, fullname, sys.exc_info())
240 try:
241 os.rmdir(path)
242 except os.error:
243 onerror(os.rmdir, path, sys.exc_info())
Guido van Rossumd7673291998-02-06 21:38:09 +0000244
Martin v. Löwise9ce0b02002-10-07 13:23:24 +0000245
Christian Heimesada8c3b2008-03-18 18:26:33 +0000246def _basename(path):
247 # A basename() variant which first strips the trailing slash, if present.
248 # Thus we always get the last component of the path, even for directories.
249 return os.path.basename(path.rstrip(os.path.sep))
250
251def move(src, dst):
252 """Recursively move a file or directory to another location. This is
253 similar to the Unix "mv" command.
254
255 If the destination is a directory or a symlink to a directory, the source
256 is moved inside the directory. The destination path must not already
257 exist.
258
259 If the destination already exists but is not a directory, it may be
260 overwritten depending on os.rename() semantics.
261
262 If the destination is on our current filesystem, then rename() is used.
263 Otherwise, src is copied to the destination and then removed.
Martin v. Löwise9ce0b02002-10-07 13:23:24 +0000264 A lot more could be done here... A look at a mv.c shows a lot of
265 the issues this implementation glosses over.
266
267 """
Christian Heimesada8c3b2008-03-18 18:26:33 +0000268 real_dst = dst
269 if os.path.isdir(dst):
270 real_dst = os.path.join(dst, _basename(src))
271 if os.path.exists(real_dst):
272 raise Error("Destination path '%s' already exists" % real_dst)
Martin v. Löwise9ce0b02002-10-07 13:23:24 +0000273 try:
Christian Heimesada8c3b2008-03-18 18:26:33 +0000274 os.rename(src, real_dst)
Martin v. Löwise9ce0b02002-10-07 13:23:24 +0000275 except OSError:
276 if os.path.isdir(src):
Benjamin Peterson247a9b82009-02-20 04:09:19 +0000277 if _destinsrc(src, dst):
Collin Winterce36ad82007-08-30 01:19:48 +0000278 raise Error("Cannot move a directory '%s' into itself '%s'." % (src, dst))
Christian Heimesada8c3b2008-03-18 18:26:33 +0000279 copytree(src, real_dst, symlinks=True)
Martin v. Löwise9ce0b02002-10-07 13:23:24 +0000280 rmtree(src)
281 else:
Christian Heimesada8c3b2008-03-18 18:26:33 +0000282 copy2(src, real_dst)
Martin v. Löwise9ce0b02002-10-07 13:23:24 +0000283 os.unlink(src)
Brett Cannon1c3fa182004-06-19 21:11:35 +0000284
Benjamin Peterson247a9b82009-02-20 04:09:19 +0000285def _destinsrc(src, dst):
Antoine Pitrou0dcc3cd2009-01-29 20:26:59 +0000286 src = abspath(src)
287 dst = abspath(dst)
288 if not src.endswith(os.path.sep):
289 src += os.path.sep
290 if not dst.endswith(os.path.sep):
291 dst += os.path.sep
292 return dst.startswith(src)