blob: 4b62cbb637c75463ee03031f9001a45be0164952 [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 Brandle78fbcc2008-07-05 10:13:36 +000011import fnmatch
Antoine Pitrouab5a9992010-03-22 20:03:59 +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",
Raymond Hettinger2b9bfb32002-10-30 05:44:50 +000015 "copytree","move","rmtree","Error"]
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 Pitrou9fcd4b32008-08-11 17:21:36 +000020try:
21 WindowsError
22except NameError:
23 WindowsError = None
24
Greg Stein42bb8b32000-07-12 09:55:30 +000025def copyfileobj(fsrc, fdst, length=16*1024):
26 """copy data from file-like object fsrc to file-like object fdst"""
27 while 1:
28 buf = fsrc.read(length)
29 if not buf:
30 break
31 fdst.write(buf)
32
Johannes Gijsbers46f14592004-08-14 13:30:02 +000033def _samefile(src, dst):
34 # Macintosh, Unix.
35 if hasattr(os.path,'samefile'):
Johannes Gijsbersf9a098e2004-08-14 14:51:01 +000036 try:
37 return os.path.samefile(src, dst)
38 except OSError:
39 return False
Johannes Gijsbers46f14592004-08-14 13:30:02 +000040
41 # All other platforms: check for same pathname.
42 return (os.path.normcase(os.path.abspath(src)) ==
43 os.path.normcase(os.path.abspath(dst)))
Tim Peters495ad3c2001-01-15 01:36:40 +000044
Guido van Rossumc6360141990-10-13 19:23:40 +000045def copyfile(src, dst):
Guido van Rossum9d0a3df1997-04-29 14:45:19 +000046 """Copy data from src to dst"""
Johannes Gijsbers46f14592004-08-14 13:30:02 +000047 if _samefile(src, dst):
48 raise Error, "`%s` and `%s` are the same file" % (src, dst)
49
Guido van Rossuma2baf461997-04-29 14:06:46 +000050 fsrc = None
51 fdst = None
52 try:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +000053 fsrc = open(src, 'rb')
54 fdst = open(dst, 'wb')
Greg Stein42bb8b32000-07-12 09:55:30 +000055 copyfileobj(fsrc, fdst)
Guido van Rossuma2baf461997-04-29 14:06:46 +000056 finally:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +000057 if fdst:
58 fdst.close()
59 if fsrc:
60 fsrc.close()
Guido van Rossumc6360141990-10-13 19:23:40 +000061
Guido van Rossumc6360141990-10-13 19:23:40 +000062def copymode(src, dst):
Guido van Rossum9d0a3df1997-04-29 14:45:19 +000063 """Copy mode bits from src to dst"""
Tim Peters0c947242001-01-21 20:00:00 +000064 if hasattr(os, 'chmod'):
65 st = os.stat(src)
Walter Dörwald294bbf32002-06-06 09:48:13 +000066 mode = stat.S_IMODE(st.st_mode)
Tim Peters0c947242001-01-21 20:00:00 +000067 os.chmod(dst, mode)
Guido van Rossumc6360141990-10-13 19:23:40 +000068
Guido van Rossumc6360141990-10-13 19:23:40 +000069def copystat(src, dst):
Martin v. Löwis382abef2007-02-19 10:55:19 +000070 """Copy all stat info (mode bits, atime, mtime, flags) from src to dst"""
Guido van Rossuma2baf461997-04-29 14:06:46 +000071 st = os.stat(src)
Walter Dörwald294bbf32002-06-06 09:48:13 +000072 mode = stat.S_IMODE(st.st_mode)
Tim Peters0c947242001-01-21 20:00:00 +000073 if hasattr(os, 'utime'):
Walter Dörwald294bbf32002-06-06 09:48:13 +000074 os.utime(dst, (st.st_atime, st.st_mtime))
Tim Peters0c947242001-01-21 20:00:00 +000075 if hasattr(os, 'chmod'):
76 os.chmod(dst, mode)
Martin v. Löwis382abef2007-02-19 10:55:19 +000077 if hasattr(os, 'chflags') and hasattr(st, 'st_flags'):
Antoine Pitrouab5a9992010-03-22 20:03:59 +000078 try:
79 os.chflags(dst, st.st_flags)
80 except OSError, why:
81 if not hasattr(errno, 'EOPNOTSUPP') or why.errno != errno.EOPNOTSUPP:
82 raise
Guido van Rossum9d0a3df1997-04-29 14:45:19 +000083
Guido van Rossumc6360141990-10-13 19:23:40 +000084def copy(src, dst):
Guido van Rossum9d0a3df1997-04-29 14:45:19 +000085 """Copy data and mode bits ("cp src dst").
Tim Peters495ad3c2001-01-15 01:36:40 +000086
Guido van Rossum9d0a3df1997-04-29 14:45:19 +000087 The destination may be a directory.
88
89 """
Guido van Rossuma2baf461997-04-29 14:06:46 +000090 if os.path.isdir(dst):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +000091 dst = os.path.join(dst, os.path.basename(src))
Guido van Rossuma2baf461997-04-29 14:06:46 +000092 copyfile(src, dst)
93 copymode(src, dst)
Guido van Rossumc6360141990-10-13 19:23:40 +000094
Guido van Rossumc6360141990-10-13 19:23:40 +000095def copy2(src, dst):
Guido van Rossum9d0a3df1997-04-29 14:45:19 +000096 """Copy data and all stat info ("cp -p src dst").
97
98 The destination may be a directory.
99
100 """
Guido van Rossuma2baf461997-04-29 14:06:46 +0000101 if os.path.isdir(dst):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000102 dst = os.path.join(dst, os.path.basename(src))
Guido van Rossuma2baf461997-04-29 14:06:46 +0000103 copyfile(src, dst)
104 copystat(src, dst)
Guido van Rossumc6360141990-10-13 19:23:40 +0000105
Georg Brandle78fbcc2008-07-05 10:13:36 +0000106def ignore_patterns(*patterns):
107 """Function that can be used as copytree() ignore parameter.
Guido van Rossum9d0a3df1997-04-29 14:45:19 +0000108
Georg Brandle78fbcc2008-07-05 10:13:36 +0000109 Patterns is a sequence of glob-style patterns
110 that are used to exclude files"""
111 def _ignore_patterns(path, names):
112 ignored_names = []
113 for pattern in patterns:
114 ignored_names.extend(fnmatch.filter(names, pattern))
115 return set(ignored_names)
116 return _ignore_patterns
117
118def copytree(src, dst, symlinks=False, ignore=None):
Guido van Rossum9d0a3df1997-04-29 14:45:19 +0000119 """Recursively copy a directory tree using copy2().
120
121 The destination directory must not already exist.
Neal Norwitza4c93b62003-02-23 21:36:32 +0000122 If exception(s) occur, an Error is raised with a list of reasons.
Guido van Rossum9d0a3df1997-04-29 14:45:19 +0000123
124 If the optional symlinks flag is true, symbolic links in the
125 source tree result in symbolic links in the destination tree; if
126 it is false, the contents of the files pointed to by symbolic
127 links are copied.
128
Georg Brandle78fbcc2008-07-05 10:13:36 +0000129 The optional ignore argument is a callable. If given, it
130 is called with the `src` parameter, which is the directory
131 being visited by copytree(), and `names` which is the list of
132 `src` contents, as returned by os.listdir():
133
134 callable(src, names) -> ignored_names
135
136 Since copytree() is called recursively, the callable will be
137 called once for each directory that is copied. It returns a
138 list of names relative to the `src` directory that should
139 not be copied.
140
Guido van Rossum9d0a3df1997-04-29 14:45:19 +0000141 XXX Consider this example code rather than the ultimate tool.
142
143 """
Guido van Rossuma2baf461997-04-29 14:06:46 +0000144 names = os.listdir(src)
Georg Brandle78fbcc2008-07-05 10:13:36 +0000145 if ignore is not None:
146 ignored_names = ignore(src, names)
147 else:
148 ignored_names = set()
149
Johannes Gijsberse4172ea2005-01-08 12:31:29 +0000150 os.makedirs(dst)
Martin v. Löwise9ce0b02002-10-07 13:23:24 +0000151 errors = []
Guido van Rossuma2baf461997-04-29 14:06:46 +0000152 for name in names:
Georg Brandle78fbcc2008-07-05 10:13:36 +0000153 if name in ignored_names:
154 continue
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000155 srcname = os.path.join(src, name)
156 dstname = os.path.join(dst, name)
157 try:
158 if symlinks and os.path.islink(srcname):
159 linkto = os.readlink(srcname)
160 os.symlink(linkto, dstname)
161 elif os.path.isdir(srcname):
Georg Brandle78fbcc2008-07-05 10:13:36 +0000162 copytree(srcname, dstname, symlinks, ignore)
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000163 else:
164 copy2(srcname, dstname)
165 # XXX What about devices, sockets etc.?
166 except (IOError, os.error), why:
Georg Brandl7a3fd892006-04-28 16:54:25 +0000167 errors.append((srcname, dstname, str(why)))
Georg Brandla1be88e2005-08-31 22:48:45 +0000168 # catch the Error from the recursive copytree so that we can
169 # continue with other files
170 except Error, err:
171 errors.extend(err.args[0])
Martin v. Löwis4e678382006-07-30 13:00:31 +0000172 try:
173 copystat(src, dst)
Martin v. Löwis4e678382006-07-30 13:00:31 +0000174 except OSError, why:
Antoine Pitrou9fcd4b32008-08-11 17:21:36 +0000175 if WindowsError is not None and isinstance(why, WindowsError):
176 # Copying file access times may fail on Windows
177 pass
178 else:
179 errors.extend((src, dst, str(why)))
Martin v. Löwise9ce0b02002-10-07 13:23:24 +0000180 if errors:
181 raise Error, errors
Guido van Rossumd7673291998-02-06 21:38:09 +0000182
Barry Warsaw234d9a92003-01-24 17:36:15 +0000183def rmtree(path, ignore_errors=False, onerror=None):
Guido van Rossumd7673291998-02-06 21:38:09 +0000184 """Recursively delete a directory tree.
185
Johannes Gijsbersef5ffc42004-10-31 12:05:31 +0000186 If ignore_errors is set, errors are ignored; otherwise, if onerror
187 is set, it is called to handle the error with arguments (func,
188 path, exc_info) where func is os.listdir, os.remove, or os.rmdir;
189 path is the argument to that function that caused it to fail; and
190 exc_info is a tuple returned by sys.exc_info(). If ignore_errors
191 is false and onerror is None, an exception is raised.
192
Guido van Rossumd7673291998-02-06 21:38:09 +0000193 """
Johannes Gijsbersef5ffc42004-10-31 12:05:31 +0000194 if ignore_errors:
195 def onerror(*args):
Barry Warsaw234d9a92003-01-24 17:36:15 +0000196 pass
Johannes Gijsbersef5ffc42004-10-31 12:05:31 +0000197 elif onerror is None:
198 def onerror(*args):
199 raise
Georg Brandl52353982008-01-20 14:17:42 +0000200 try:
201 if os.path.islink(path):
202 # symlinks to directories are forbidden, see bug #1669
203 raise OSError("Cannot call rmtree on a symbolic link")
204 except OSError:
205 onerror(os.path.islink, path, sys.exc_info())
206 # can't continue even if onerror hook returns
207 return
Johannes Gijsbersef5ffc42004-10-31 12:05:31 +0000208 names = []
209 try:
210 names = os.listdir(path)
211 except os.error, err:
212 onerror(os.listdir, path, sys.exc_info())
213 for name in names:
214 fullname = os.path.join(path, name)
215 try:
216 mode = os.lstat(fullname).st_mode
217 except os.error:
218 mode = 0
219 if stat.S_ISDIR(mode):
220 rmtree(fullname, ignore_errors, onerror)
Barry Warsaw234d9a92003-01-24 17:36:15 +0000221 else:
Johannes Gijsbersef5ffc42004-10-31 12:05:31 +0000222 try:
223 os.remove(fullname)
224 except os.error, err:
225 onerror(os.remove, fullname, sys.exc_info())
226 try:
227 os.rmdir(path)
228 except os.error:
229 onerror(os.rmdir, path, sys.exc_info())
Guido van Rossumd7673291998-02-06 21:38:09 +0000230
Martin v. Löwise9ce0b02002-10-07 13:23:24 +0000231
Sean Reifscheider493894c2008-03-18 17:24:12 +0000232def _basename(path):
233 # A basename() variant which first strips the trailing slash, if present.
234 # Thus we always get the last component of the path, even for directories.
235 return os.path.basename(path.rstrip(os.path.sep))
236
237def move(src, dst):
238 """Recursively move a file or directory to another location. This is
239 similar to the Unix "mv" command.
240
241 If the destination is a directory or a symlink to a directory, the source
242 is moved inside the directory. The destination path must not already
243 exist.
244
245 If the destination already exists but is not a directory, it may be
246 overwritten depending on os.rename() semantics.
247
248 If the destination is on our current filesystem, then rename() is used.
249 Otherwise, src is copied to the destination and then removed.
Martin v. Löwise9ce0b02002-10-07 13:23:24 +0000250 A lot more could be done here... A look at a mv.c shows a lot of
251 the issues this implementation glosses over.
252
253 """
Sean Reifscheider493894c2008-03-18 17:24:12 +0000254 real_dst = dst
255 if os.path.isdir(dst):
256 real_dst = os.path.join(dst, _basename(src))
257 if os.path.exists(real_dst):
258 raise Error, "Destination path '%s' already exists" % real_dst
Martin v. Löwise9ce0b02002-10-07 13:23:24 +0000259 try:
Sean Reifscheider493894c2008-03-18 17:24:12 +0000260 os.rename(src, real_dst)
Martin v. Löwise9ce0b02002-10-07 13:23:24 +0000261 except OSError:
262 if os.path.isdir(src):
Brett Cannon1c3fa182004-06-19 21:11:35 +0000263 if destinsrc(src, dst):
264 raise Error, "Cannot move a directory '%s' into itself '%s'." % (src, dst)
Sean Reifscheider493894c2008-03-18 17:24:12 +0000265 copytree(src, real_dst, symlinks=True)
Martin v. Löwise9ce0b02002-10-07 13:23:24 +0000266 rmtree(src)
267 else:
Sean Reifscheider493894c2008-03-18 17:24:12 +0000268 copy2(src, real_dst)
Martin v. Löwise9ce0b02002-10-07 13:23:24 +0000269 os.unlink(src)
Brett Cannon1c3fa182004-06-19 21:11:35 +0000270
271def destinsrc(src, dst):
Antoine Pitrou4ad77e22009-01-29 20:30:51 +0000272 src = abspath(src)
273 dst = abspath(dst)
274 if not src.endswith(os.path.sep):
275 src += os.path.sep
276 if not dst.endswith(os.path.sep):
277 dst += os.path.sep
278 return dst.startswith(src)