blob: 4c182aef037294eb19532b29362bde17cd80d7dd [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):
Tarek Ziadé06f78cd2010-05-05 22:21:13 +000048 raise Error("`%s` and `%s` are the same file" % (src, dst))
Johannes Gijsbers46f14592004-08-14 13:30:02 +000049
Tarek Ziadé06f78cd2010-05-05 22:21:13 +000050 with open(src, 'rb') as fsrc:
51 with open(dst, 'wb') as fdst:
52 copyfileobj(fsrc, fdst)
Guido van Rossumc6360141990-10-13 19:23:40 +000053
Guido van Rossumc6360141990-10-13 19:23:40 +000054def copymode(src, dst):
Guido van Rossum9d0a3df1997-04-29 14:45:19 +000055 """Copy mode bits from src to dst"""
Tim Peters0c947242001-01-21 20:00:00 +000056 if hasattr(os, 'chmod'):
57 st = os.stat(src)
Walter Dörwald294bbf32002-06-06 09:48:13 +000058 mode = stat.S_IMODE(st.st_mode)
Tim Peters0c947242001-01-21 20:00:00 +000059 os.chmod(dst, mode)
Guido van Rossumc6360141990-10-13 19:23:40 +000060
Guido van Rossumc6360141990-10-13 19:23:40 +000061def copystat(src, dst):
Martin v. Löwis382abef2007-02-19 10:55:19 +000062 """Copy all stat info (mode bits, atime, mtime, flags) from src to dst"""
Guido van Rossuma2baf461997-04-29 14:06:46 +000063 st = os.stat(src)
Walter Dörwald294bbf32002-06-06 09:48:13 +000064 mode = stat.S_IMODE(st.st_mode)
Tim Peters0c947242001-01-21 20:00:00 +000065 if hasattr(os, 'utime'):
Walter Dörwald294bbf32002-06-06 09:48:13 +000066 os.utime(dst, (st.st_atime, st.st_mtime))
Tim Peters0c947242001-01-21 20:00:00 +000067 if hasattr(os, 'chmod'):
68 os.chmod(dst, mode)
Martin v. Löwis382abef2007-02-19 10:55:19 +000069 if hasattr(os, 'chflags') and hasattr(st, 'st_flags'):
Antoine Pitrouab5a9992010-03-22 20:03:59 +000070 try:
71 os.chflags(dst, st.st_flags)
72 except OSError, why:
73 if not hasattr(errno, 'EOPNOTSUPP') or why.errno != errno.EOPNOTSUPP:
74 raise
Guido van Rossum9d0a3df1997-04-29 14:45:19 +000075
Guido van Rossumc6360141990-10-13 19:23:40 +000076def copy(src, dst):
Guido van Rossum9d0a3df1997-04-29 14:45:19 +000077 """Copy data and mode bits ("cp src dst").
Tim Peters495ad3c2001-01-15 01:36:40 +000078
Guido van Rossum9d0a3df1997-04-29 14:45:19 +000079 The destination may be a directory.
80
81 """
Guido van Rossuma2baf461997-04-29 14:06:46 +000082 if os.path.isdir(dst):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +000083 dst = os.path.join(dst, os.path.basename(src))
Guido van Rossuma2baf461997-04-29 14:06:46 +000084 copyfile(src, dst)
85 copymode(src, dst)
Guido van Rossumc6360141990-10-13 19:23:40 +000086
Guido van Rossumc6360141990-10-13 19:23:40 +000087def copy2(src, dst):
Guido van Rossum9d0a3df1997-04-29 14:45:19 +000088 """Copy data and all stat info ("cp -p src dst").
89
90 The destination may be a directory.
91
92 """
Guido van Rossuma2baf461997-04-29 14:06:46 +000093 if os.path.isdir(dst):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +000094 dst = os.path.join(dst, os.path.basename(src))
Guido van Rossuma2baf461997-04-29 14:06:46 +000095 copyfile(src, dst)
96 copystat(src, dst)
Guido van Rossumc6360141990-10-13 19:23:40 +000097
Georg Brandle78fbcc2008-07-05 10:13:36 +000098def ignore_patterns(*patterns):
99 """Function that can be used as copytree() ignore parameter.
Guido van Rossum9d0a3df1997-04-29 14:45:19 +0000100
Georg Brandle78fbcc2008-07-05 10:13:36 +0000101 Patterns is a sequence of glob-style patterns
102 that are used to exclude files"""
103 def _ignore_patterns(path, names):
104 ignored_names = []
105 for pattern in patterns:
106 ignored_names.extend(fnmatch.filter(names, pattern))
107 return set(ignored_names)
108 return _ignore_patterns
109
110def copytree(src, dst, symlinks=False, ignore=None):
Guido van Rossum9d0a3df1997-04-29 14:45:19 +0000111 """Recursively copy a directory tree using copy2().
112
113 The destination directory must not already exist.
Neal Norwitza4c93b62003-02-23 21:36:32 +0000114 If exception(s) occur, an Error is raised with a list of reasons.
Guido van Rossum9d0a3df1997-04-29 14:45:19 +0000115
116 If the optional symlinks flag is true, symbolic links in the
117 source tree result in symbolic links in the destination tree; if
118 it is false, the contents of the files pointed to by symbolic
119 links are copied.
120
Georg Brandle78fbcc2008-07-05 10:13:36 +0000121 The optional ignore argument is a callable. If given, it
122 is called with the `src` parameter, which is the directory
123 being visited by copytree(), and `names` which is the list of
124 `src` contents, as returned by os.listdir():
125
126 callable(src, names) -> ignored_names
127
128 Since copytree() is called recursively, the callable will be
129 called once for each directory that is copied. It returns a
130 list of names relative to the `src` directory that should
131 not be copied.
132
Guido van Rossum9d0a3df1997-04-29 14:45:19 +0000133 XXX Consider this example code rather than the ultimate tool.
134
135 """
Guido van Rossuma2baf461997-04-29 14:06:46 +0000136 names = os.listdir(src)
Georg Brandle78fbcc2008-07-05 10:13:36 +0000137 if ignore is not None:
138 ignored_names = ignore(src, names)
139 else:
140 ignored_names = set()
141
Johannes Gijsberse4172ea2005-01-08 12:31:29 +0000142 os.makedirs(dst)
Martin v. Löwise9ce0b02002-10-07 13:23:24 +0000143 errors = []
Guido van Rossuma2baf461997-04-29 14:06:46 +0000144 for name in names:
Georg Brandle78fbcc2008-07-05 10:13:36 +0000145 if name in ignored_names:
146 continue
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000147 srcname = os.path.join(src, name)
148 dstname = os.path.join(dst, name)
149 try:
150 if symlinks and os.path.islink(srcname):
151 linkto = os.readlink(srcname)
152 os.symlink(linkto, dstname)
153 elif os.path.isdir(srcname):
Georg Brandle78fbcc2008-07-05 10:13:36 +0000154 copytree(srcname, dstname, symlinks, ignore)
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000155 else:
156 copy2(srcname, dstname)
157 # XXX What about devices, sockets etc.?
158 except (IOError, os.error), why:
Georg Brandl7a3fd892006-04-28 16:54:25 +0000159 errors.append((srcname, dstname, str(why)))
Georg Brandla1be88e2005-08-31 22:48:45 +0000160 # catch the Error from the recursive copytree so that we can
161 # continue with other files
162 except Error, err:
163 errors.extend(err.args[0])
Martin v. Löwis4e678382006-07-30 13:00:31 +0000164 try:
165 copystat(src, dst)
Martin v. Löwis4e678382006-07-30 13:00:31 +0000166 except OSError, why:
Antoine Pitrou9fcd4b32008-08-11 17:21:36 +0000167 if WindowsError is not None and isinstance(why, WindowsError):
168 # Copying file access times may fail on Windows
169 pass
170 else:
171 errors.extend((src, dst, str(why)))
Martin v. Löwise9ce0b02002-10-07 13:23:24 +0000172 if errors:
173 raise Error, errors
Guido van Rossumd7673291998-02-06 21:38:09 +0000174
Barry Warsaw234d9a92003-01-24 17:36:15 +0000175def rmtree(path, ignore_errors=False, onerror=None):
Guido van Rossumd7673291998-02-06 21:38:09 +0000176 """Recursively delete a directory tree.
177
Johannes Gijsbersef5ffc42004-10-31 12:05:31 +0000178 If ignore_errors is set, errors are ignored; otherwise, if onerror
179 is set, it is called to handle the error with arguments (func,
180 path, exc_info) where func is os.listdir, os.remove, or os.rmdir;
181 path is the argument to that function that caused it to fail; and
182 exc_info is a tuple returned by sys.exc_info(). If ignore_errors
183 is false and onerror is None, an exception is raised.
184
Guido van Rossumd7673291998-02-06 21:38:09 +0000185 """
Johannes Gijsbersef5ffc42004-10-31 12:05:31 +0000186 if ignore_errors:
187 def onerror(*args):
Barry Warsaw234d9a92003-01-24 17:36:15 +0000188 pass
Johannes Gijsbersef5ffc42004-10-31 12:05:31 +0000189 elif onerror is None:
190 def onerror(*args):
191 raise
Georg Brandl52353982008-01-20 14:17:42 +0000192 try:
193 if os.path.islink(path):
194 # symlinks to directories are forbidden, see bug #1669
195 raise OSError("Cannot call rmtree on a symbolic link")
196 except OSError:
197 onerror(os.path.islink, path, sys.exc_info())
198 # can't continue even if onerror hook returns
199 return
Johannes Gijsbersef5ffc42004-10-31 12:05:31 +0000200 names = []
201 try:
202 names = os.listdir(path)
203 except os.error, err:
204 onerror(os.listdir, path, sys.exc_info())
205 for name in names:
206 fullname = os.path.join(path, name)
207 try:
208 mode = os.lstat(fullname).st_mode
209 except os.error:
210 mode = 0
211 if stat.S_ISDIR(mode):
212 rmtree(fullname, ignore_errors, onerror)
Barry Warsaw234d9a92003-01-24 17:36:15 +0000213 else:
Johannes Gijsbersef5ffc42004-10-31 12:05:31 +0000214 try:
215 os.remove(fullname)
216 except os.error, err:
217 onerror(os.remove, fullname, sys.exc_info())
218 try:
219 os.rmdir(path)
220 except os.error:
221 onerror(os.rmdir, path, sys.exc_info())
Guido van Rossumd7673291998-02-06 21:38:09 +0000222
Martin v. Löwise9ce0b02002-10-07 13:23:24 +0000223
Sean Reifscheider493894c2008-03-18 17:24:12 +0000224def _basename(path):
225 # A basename() variant which first strips the trailing slash, if present.
226 # Thus we always get the last component of the path, even for directories.
227 return os.path.basename(path.rstrip(os.path.sep))
228
229def move(src, dst):
230 """Recursively move a file or directory to another location. This is
231 similar to the Unix "mv" command.
232
233 If the destination is a directory or a symlink to a directory, the source
234 is moved inside the directory. The destination path must not already
235 exist.
236
237 If the destination already exists but is not a directory, it may be
238 overwritten depending on os.rename() semantics.
239
240 If the destination is on our current filesystem, then rename() is used.
241 Otherwise, src is copied to the destination and then removed.
Martin v. Löwise9ce0b02002-10-07 13:23:24 +0000242 A lot more could be done here... A look at a mv.c shows a lot of
243 the issues this implementation glosses over.
244
245 """
Sean Reifscheider493894c2008-03-18 17:24:12 +0000246 real_dst = dst
247 if os.path.isdir(dst):
248 real_dst = os.path.join(dst, _basename(src))
249 if os.path.exists(real_dst):
250 raise Error, "Destination path '%s' already exists" % real_dst
Martin v. Löwise9ce0b02002-10-07 13:23:24 +0000251 try:
Sean Reifscheider493894c2008-03-18 17:24:12 +0000252 os.rename(src, real_dst)
Martin v. Löwise9ce0b02002-10-07 13:23:24 +0000253 except OSError:
254 if os.path.isdir(src):
Brett Cannon1c3fa182004-06-19 21:11:35 +0000255 if destinsrc(src, dst):
256 raise Error, "Cannot move a directory '%s' into itself '%s'." % (src, dst)
Sean Reifscheider493894c2008-03-18 17:24:12 +0000257 copytree(src, real_dst, symlinks=True)
Martin v. Löwise9ce0b02002-10-07 13:23:24 +0000258 rmtree(src)
259 else:
Sean Reifscheider493894c2008-03-18 17:24:12 +0000260 copy2(src, real_dst)
Martin v. Löwise9ce0b02002-10-07 13:23:24 +0000261 os.unlink(src)
Brett Cannon1c3fa182004-06-19 21:11:35 +0000262
263def destinsrc(src, dst):
Antoine Pitrou4ad77e22009-01-29 20:30:51 +0000264 src = abspath(src)
265 dst = abspath(dst)
266 if not src.endswith(os.path.sep):
267 src += os.path.sep
268 if not dst.endswith(os.path.sep):
269 dst += os.path.sep
270 return dst.startswith(src)