blob: dc36820dc9a77c893bf4c58ce0d81cabb9a88eb0 [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
Guido van Rossumc6360141990-10-13 19:23:40 +000012
Skip Montanaro0de65802001-02-15 22:15:14 +000013__all__ = ["copyfileobj","copyfile","copymode","copystat","copy","copy2",
Antoine Pitrou7fff0962009-05-01 21:09:44 +000014 "copytree","move","rmtree","Error", "SpecialFileError"]
Martin v. Löwise9ce0b02002-10-07 13:23:24 +000015
Neal Norwitz4ce69a52005-09-01 00:45:28 +000016class Error(EnvironmentError):
Martin v. Löwise9ce0b02002-10-07 13:23:24 +000017 pass
Guido van Rossumc6360141990-10-13 19:23:40 +000018
Antoine Pitrou7fff0962009-05-01 21:09:44 +000019class SpecialFileError(EnvironmentError):
20 """Raised when trying to do a kind of operation (e.g. copying) which is
21 not supported on a special file (e.g. a named pipe)"""
22
Georg Brandl6aa2d1f2008-08-12 08:35:52 +000023try:
24 WindowsError
25except NameError:
26 WindowsError = None
27
Greg Stein42bb8b32000-07-12 09:55:30 +000028def copyfileobj(fsrc, fdst, length=16*1024):
29 """copy data from file-like object fsrc to file-like object fdst"""
30 while 1:
31 buf = fsrc.read(length)
32 if not buf:
33 break
34 fdst.write(buf)
35
Johannes Gijsbers46f14592004-08-14 13:30:02 +000036def _samefile(src, dst):
37 # Macintosh, Unix.
38 if hasattr(os.path,'samefile'):
Johannes Gijsbersf9a098e2004-08-14 14:51:01 +000039 try:
40 return os.path.samefile(src, dst)
41 except OSError:
42 return False
Johannes Gijsbers46f14592004-08-14 13:30:02 +000043
44 # All other platforms: check for same pathname.
45 return (os.path.normcase(os.path.abspath(src)) ==
46 os.path.normcase(os.path.abspath(dst)))
Tim Peters495ad3c2001-01-15 01:36:40 +000047
Guido van Rossumc6360141990-10-13 19:23:40 +000048def copyfile(src, dst):
Guido van Rossum9d0a3df1997-04-29 14:45:19 +000049 """Copy data from src to dst"""
Johannes Gijsbers46f14592004-08-14 13:30:02 +000050 if _samefile(src, dst):
Collin Winterce36ad82007-08-30 01:19:48 +000051 raise Error("`%s` and `%s` are the same file" % (src, dst))
Johannes Gijsbers46f14592004-08-14 13:30:02 +000052
Guido van Rossuma2baf461997-04-29 14:06:46 +000053 fsrc = None
54 fdst = None
Antoine Pitrou7fff0962009-05-01 21:09:44 +000055 for fn in [src, dst]:
56 try:
57 st = os.stat(fn)
58 except OSError:
59 # File most likely does not exist
60 pass
Benjamin Petersonc0d98aa2009-06-05 19:13:27 +000061 else:
62 # XXX What about other special files? (sockets, devices...)
63 if stat.S_ISFIFO(st.st_mode):
64 raise SpecialFileError("`%s` is a named pipe" % fn)
Guido van Rossuma2baf461997-04-29 14:06:46 +000065 try:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +000066 fsrc = open(src, 'rb')
67 fdst = open(dst, 'wb')
Greg Stein42bb8b32000-07-12 09:55:30 +000068 copyfileobj(fsrc, fdst)
Guido van Rossuma2baf461997-04-29 14:06:46 +000069 finally:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +000070 if fdst:
71 fdst.close()
72 if fsrc:
73 fsrc.close()
Guido van Rossumc6360141990-10-13 19:23:40 +000074
Guido van Rossumc6360141990-10-13 19:23:40 +000075def copymode(src, dst):
Guido van Rossum9d0a3df1997-04-29 14:45:19 +000076 """Copy mode bits from src to dst"""
Tim Peters0c947242001-01-21 20:00:00 +000077 if hasattr(os, 'chmod'):
78 st = os.stat(src)
Walter Dörwald294bbf32002-06-06 09:48:13 +000079 mode = stat.S_IMODE(st.st_mode)
Tim Peters0c947242001-01-21 20:00:00 +000080 os.chmod(dst, mode)
Guido van Rossumc6360141990-10-13 19:23:40 +000081
Guido van Rossumc6360141990-10-13 19:23:40 +000082def copystat(src, dst):
Thomas Wouterscf297e42007-02-23 15:07:44 +000083 """Copy all stat info (mode bits, atime, mtime, flags) from src to dst"""
Guido van Rossuma2baf461997-04-29 14:06:46 +000084 st = os.stat(src)
Walter Dörwald294bbf32002-06-06 09:48:13 +000085 mode = stat.S_IMODE(st.st_mode)
Tim Peters0c947242001-01-21 20:00:00 +000086 if hasattr(os, 'utime'):
Walter Dörwald294bbf32002-06-06 09:48:13 +000087 os.utime(dst, (st.st_atime, st.st_mtime))
Tim Peters0c947242001-01-21 20:00:00 +000088 if hasattr(os, 'chmod'):
89 os.chmod(dst, mode)
Thomas Wouterscf297e42007-02-23 15:07:44 +000090 if hasattr(os, 'chflags') and hasattr(st, 'st_flags'):
91 os.chflags(dst, st.st_flags)
Guido van Rossumc6360141990-10-13 19:23:40 +000092
Guido van Rossum9d0a3df1997-04-29 14:45:19 +000093
Guido van Rossumc6360141990-10-13 19:23:40 +000094def copy(src, dst):
Guido van Rossum9d0a3df1997-04-29 14:45:19 +000095 """Copy data and mode bits ("cp src dst").
Tim Peters495ad3c2001-01-15 01:36:40 +000096
Guido van Rossum9d0a3df1997-04-29 14:45:19 +000097 The destination may be a directory.
98
99 """
Guido van Rossuma2baf461997-04-29 14:06:46 +0000100 if os.path.isdir(dst):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000101 dst = os.path.join(dst, os.path.basename(src))
Guido van Rossuma2baf461997-04-29 14:06:46 +0000102 copyfile(src, dst)
103 copymode(src, dst)
Guido van Rossumc6360141990-10-13 19:23:40 +0000104
Guido van Rossumc6360141990-10-13 19:23:40 +0000105def copy2(src, dst):
Guido van Rossum9d0a3df1997-04-29 14:45:19 +0000106 """Copy data and all stat info ("cp -p src dst").
107
108 The destination may be a directory.
109
110 """
Guido van Rossuma2baf461997-04-29 14:06:46 +0000111 if os.path.isdir(dst):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000112 dst = os.path.join(dst, os.path.basename(src))
Guido van Rossuma2baf461997-04-29 14:06:46 +0000113 copyfile(src, dst)
114 copystat(src, dst)
Guido van Rossumc6360141990-10-13 19:23:40 +0000115
Georg Brandl2ee470f2008-07-16 12:55:28 +0000116def ignore_patterns(*patterns):
117 """Function that can be used as copytree() ignore parameter.
Guido van Rossum9d0a3df1997-04-29 14:45:19 +0000118
Georg Brandl2ee470f2008-07-16 12:55:28 +0000119 Patterns is a sequence of glob-style patterns
120 that are used to exclude files"""
121 def _ignore_patterns(path, names):
122 ignored_names = []
123 for pattern in patterns:
124 ignored_names.extend(fnmatch.filter(names, pattern))
125 return set(ignored_names)
126 return _ignore_patterns
127
128def copytree(src, dst, symlinks=False, ignore=None):
Guido van Rossum9d0a3df1997-04-29 14:45:19 +0000129 """Recursively copy a directory tree using copy2().
130
131 The destination directory must not already exist.
Neal Norwitza4c93b62003-02-23 21:36:32 +0000132 If exception(s) occur, an Error is raised with a list of reasons.
Guido van Rossum9d0a3df1997-04-29 14:45:19 +0000133
134 If the optional symlinks flag is true, symbolic links in the
135 source tree result in symbolic links in the destination tree; if
136 it is false, the contents of the files pointed to by symbolic
137 links are copied.
138
Georg Brandl2ee470f2008-07-16 12:55:28 +0000139 The optional ignore argument is a callable. If given, it
140 is called with the `src` parameter, which is the directory
141 being visited by copytree(), and `names` which is the list of
142 `src` contents, as returned by os.listdir():
143
144 callable(src, names) -> ignored_names
145
146 Since copytree() is called recursively, the callable will be
147 called once for each directory that is copied. It returns a
148 list of names relative to the `src` directory that should
149 not be copied.
150
Guido van Rossum9d0a3df1997-04-29 14:45:19 +0000151 XXX Consider this example code rather than the ultimate tool.
152
153 """
Guido van Rossuma2baf461997-04-29 14:06:46 +0000154 names = os.listdir(src)
Georg Brandl2ee470f2008-07-16 12:55:28 +0000155 if ignore is not None:
156 ignored_names = ignore(src, names)
157 else:
158 ignored_names = set()
159
Johannes Gijsberse4172ea2005-01-08 12:31:29 +0000160 os.makedirs(dst)
Martin v. Löwise9ce0b02002-10-07 13:23:24 +0000161 errors = []
Guido van Rossuma2baf461997-04-29 14:06:46 +0000162 for name in names:
Georg Brandl2ee470f2008-07-16 12:55:28 +0000163 if name in ignored_names:
164 continue
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000165 srcname = os.path.join(src, name)
166 dstname = os.path.join(dst, name)
167 try:
168 if symlinks and os.path.islink(srcname):
169 linkto = os.readlink(srcname)
170 os.symlink(linkto, dstname)
171 elif os.path.isdir(srcname):
Georg Brandl2ee470f2008-07-16 12:55:28 +0000172 copytree(srcname, dstname, symlinks, ignore)
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000173 else:
Antoine Pitrou7fff0962009-05-01 21:09:44 +0000174 # Will raise a SpecialFileError for unsupported file types
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000175 copy2(srcname, dstname)
Georg Brandla1be88e2005-08-31 22:48:45 +0000176 # catch the Error from the recursive copytree so that we can
177 # continue with other files
Guido van Rossumb940e112007-01-10 16:19:56 +0000178 except Error as err:
Georg Brandla1be88e2005-08-31 22:48:45 +0000179 errors.extend(err.args[0])
Antoine Pitrou7fff0962009-05-01 21:09:44 +0000180 except EnvironmentError as why:
181 errors.append((srcname, dstname, str(why)))
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000182 try:
183 copystat(src, dst)
Guido van Rossumb940e112007-01-10 16:19:56 +0000184 except OSError as why:
Georg Brandl6aa2d1f2008-08-12 08:35:52 +0000185 if WindowsError is not None and isinstance(why, WindowsError):
186 # Copying file access times may fail on Windows
187 pass
188 else:
189 errors.extend((src, dst, str(why)))
Martin v. Löwise9ce0b02002-10-07 13:23:24 +0000190 if errors:
Collin Winterce36ad82007-08-30 01:19:48 +0000191 raise Error(errors)
Guido van Rossumd7673291998-02-06 21:38:09 +0000192
Barry Warsaw234d9a92003-01-24 17:36:15 +0000193def rmtree(path, ignore_errors=False, onerror=None):
Guido van Rossumd7673291998-02-06 21:38:09 +0000194 """Recursively delete a directory tree.
195
Johannes Gijsbersef5ffc42004-10-31 12:05:31 +0000196 If ignore_errors is set, errors are ignored; otherwise, if onerror
197 is set, it is called to handle the error with arguments (func,
198 path, exc_info) where func is os.listdir, os.remove, or os.rmdir;
199 path is the argument to that function that caused it to fail; and
200 exc_info is a tuple returned by sys.exc_info(). If ignore_errors
201 is false and onerror is None, an exception is raised.
202
Guido van Rossumd7673291998-02-06 21:38:09 +0000203 """
Johannes Gijsbersef5ffc42004-10-31 12:05:31 +0000204 if ignore_errors:
205 def onerror(*args):
Barry Warsaw234d9a92003-01-24 17:36:15 +0000206 pass
Johannes Gijsbersef5ffc42004-10-31 12:05:31 +0000207 elif onerror is None:
208 def onerror(*args):
209 raise
Christian Heimes9bd667a2008-01-20 15:14:11 +0000210 try:
211 if os.path.islink(path):
212 # symlinks to directories are forbidden, see bug #1669
213 raise OSError("Cannot call rmtree on a symbolic link")
214 except OSError:
215 onerror(os.path.islink, path, sys.exc_info())
216 # can't continue even if onerror hook returns
217 return
Johannes Gijsbersef5ffc42004-10-31 12:05:31 +0000218 names = []
219 try:
220 names = os.listdir(path)
Guido van Rossumb940e112007-01-10 16:19:56 +0000221 except os.error as err:
Johannes Gijsbersef5ffc42004-10-31 12:05:31 +0000222 onerror(os.listdir, path, sys.exc_info())
223 for name in names:
224 fullname = os.path.join(path, name)
225 try:
226 mode = os.lstat(fullname).st_mode
227 except os.error:
228 mode = 0
229 if stat.S_ISDIR(mode):
230 rmtree(fullname, ignore_errors, onerror)
Barry Warsaw234d9a92003-01-24 17:36:15 +0000231 else:
Johannes Gijsbersef5ffc42004-10-31 12:05:31 +0000232 try:
233 os.remove(fullname)
Guido van Rossumb940e112007-01-10 16:19:56 +0000234 except os.error as err:
Johannes Gijsbersef5ffc42004-10-31 12:05:31 +0000235 onerror(os.remove, fullname, sys.exc_info())
236 try:
237 os.rmdir(path)
238 except os.error:
239 onerror(os.rmdir, path, sys.exc_info())
Guido van Rossumd7673291998-02-06 21:38:09 +0000240
Martin v. Löwise9ce0b02002-10-07 13:23:24 +0000241
Christian Heimesada8c3b2008-03-18 18:26:33 +0000242def _basename(path):
243 # A basename() variant which first strips the trailing slash, if present.
244 # Thus we always get the last component of the path, even for directories.
245 return os.path.basename(path.rstrip(os.path.sep))
246
247def move(src, dst):
248 """Recursively move a file or directory to another location. This is
249 similar to the Unix "mv" command.
250
251 If the destination is a directory or a symlink to a directory, the source
252 is moved inside the directory. The destination path must not already
253 exist.
254
255 If the destination already exists but is not a directory, it may be
256 overwritten depending on os.rename() semantics.
257
258 If the destination is on our current filesystem, then rename() is used.
259 Otherwise, src is copied to the destination and then removed.
Martin v. Löwise9ce0b02002-10-07 13:23:24 +0000260 A lot more could be done here... A look at a mv.c shows a lot of
261 the issues this implementation glosses over.
262
263 """
Christian Heimesada8c3b2008-03-18 18:26:33 +0000264 real_dst = dst
265 if os.path.isdir(dst):
266 real_dst = os.path.join(dst, _basename(src))
267 if os.path.exists(real_dst):
268 raise Error("Destination path '%s' already exists" % real_dst)
Martin v. Löwise9ce0b02002-10-07 13:23:24 +0000269 try:
Christian Heimesada8c3b2008-03-18 18:26:33 +0000270 os.rename(src, real_dst)
Martin v. Löwise9ce0b02002-10-07 13:23:24 +0000271 except OSError:
272 if os.path.isdir(src):
Benjamin Peterson247a9b82009-02-20 04:09:19 +0000273 if _destinsrc(src, dst):
Collin Winterce36ad82007-08-30 01:19:48 +0000274 raise Error("Cannot move a directory '%s' into itself '%s'." % (src, dst))
Christian Heimesada8c3b2008-03-18 18:26:33 +0000275 copytree(src, real_dst, symlinks=True)
Martin v. Löwise9ce0b02002-10-07 13:23:24 +0000276 rmtree(src)
277 else:
Christian Heimesada8c3b2008-03-18 18:26:33 +0000278 copy2(src, real_dst)
Martin v. Löwise9ce0b02002-10-07 13:23:24 +0000279 os.unlink(src)
Brett Cannon1c3fa182004-06-19 21:11:35 +0000280
Benjamin Peterson247a9b82009-02-20 04:09:19 +0000281def _destinsrc(src, dst):
Antoine Pitrou0dcc3cd2009-01-29 20:26:59 +0000282 src = abspath(src)
283 dst = abspath(dst)
284 if not src.endswith(os.path.sep):
285 src += os.path.sep
286 if not dst.endswith(os.path.sep):
287 dst += os.path.sep
288 return dst.startswith(src)