blob: 56ea7ec3edecee85b2a9718177295020ad28ee78 [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",
Raymond Hettinger2b9bfb32002-10-30 05:44:50 +000014 "copytree","move","rmtree","Error"]
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
Greg Stein42bb8b32000-07-12 09:55:30 +000019def copyfileobj(fsrc, fdst, length=16*1024):
20 """copy data from file-like object fsrc to file-like object fdst"""
21 while 1:
22 buf = fsrc.read(length)
23 if not buf:
24 break
25 fdst.write(buf)
26
Johannes Gijsbers46f14592004-08-14 13:30:02 +000027def _samefile(src, dst):
28 # Macintosh, Unix.
29 if hasattr(os.path,'samefile'):
Johannes Gijsbersf9a098e2004-08-14 14:51:01 +000030 try:
31 return os.path.samefile(src, dst)
32 except OSError:
33 return False
Johannes Gijsbers46f14592004-08-14 13:30:02 +000034
35 # All other platforms: check for same pathname.
36 return (os.path.normcase(os.path.abspath(src)) ==
37 os.path.normcase(os.path.abspath(dst)))
Tim Peters495ad3c2001-01-15 01:36:40 +000038
Guido van Rossumc6360141990-10-13 19:23:40 +000039def copyfile(src, dst):
Guido van Rossum9d0a3df1997-04-29 14:45:19 +000040 """Copy data from src to dst"""
Johannes Gijsbers46f14592004-08-14 13:30:02 +000041 if _samefile(src, dst):
Collin Winterce36ad82007-08-30 01:19:48 +000042 raise Error("`%s` and `%s` are the same file" % (src, dst))
Johannes Gijsbers46f14592004-08-14 13:30:02 +000043
Guido van Rossuma2baf461997-04-29 14:06:46 +000044 fsrc = None
45 fdst = None
46 try:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +000047 fsrc = open(src, 'rb')
48 fdst = open(dst, 'wb')
Greg Stein42bb8b32000-07-12 09:55:30 +000049 copyfileobj(fsrc, fdst)
Guido van Rossuma2baf461997-04-29 14:06:46 +000050 finally:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +000051 if fdst:
52 fdst.close()
53 if fsrc:
54 fsrc.close()
Guido van Rossumc6360141990-10-13 19:23:40 +000055
Guido van Rossumc6360141990-10-13 19:23:40 +000056def copymode(src, dst):
Guido van Rossum9d0a3df1997-04-29 14:45:19 +000057 """Copy mode bits from src to dst"""
Tim Peters0c947242001-01-21 20:00:00 +000058 if hasattr(os, 'chmod'):
59 st = os.stat(src)
Walter Dörwald294bbf32002-06-06 09:48:13 +000060 mode = stat.S_IMODE(st.st_mode)
Tim Peters0c947242001-01-21 20:00:00 +000061 os.chmod(dst, mode)
Guido van Rossumc6360141990-10-13 19:23:40 +000062
Guido van Rossumc6360141990-10-13 19:23:40 +000063def copystat(src, dst):
Thomas Wouterscf297e42007-02-23 15:07:44 +000064 """Copy all stat info (mode bits, atime, mtime, flags) from src to dst"""
Guido van Rossuma2baf461997-04-29 14:06:46 +000065 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 if hasattr(os, 'utime'):
Walter Dörwald294bbf32002-06-06 09:48:13 +000068 os.utime(dst, (st.st_atime, st.st_mtime))
Tim Peters0c947242001-01-21 20:00:00 +000069 if hasattr(os, 'chmod'):
70 os.chmod(dst, mode)
Thomas Wouterscf297e42007-02-23 15:07:44 +000071 if hasattr(os, 'chflags') and hasattr(st, 'st_flags'):
72 os.chflags(dst, st.st_flags)
Guido van Rossumc6360141990-10-13 19:23:40 +000073
Guido van Rossum9d0a3df1997-04-29 14:45:19 +000074
Guido van Rossumc6360141990-10-13 19:23:40 +000075def copy(src, dst):
Guido van Rossum9d0a3df1997-04-29 14:45:19 +000076 """Copy data and mode bits ("cp src dst").
Tim Peters495ad3c2001-01-15 01:36:40 +000077
Guido van Rossum9d0a3df1997-04-29 14:45:19 +000078 The destination may be a directory.
79
80 """
Guido van Rossuma2baf461997-04-29 14:06:46 +000081 if os.path.isdir(dst):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +000082 dst = os.path.join(dst, os.path.basename(src))
Guido van Rossuma2baf461997-04-29 14:06:46 +000083 copyfile(src, dst)
84 copymode(src, dst)
Guido van Rossumc6360141990-10-13 19:23:40 +000085
Guido van Rossumc6360141990-10-13 19:23:40 +000086def copy2(src, dst):
Guido van Rossum9d0a3df1997-04-29 14:45:19 +000087 """Copy data and all stat info ("cp -p src dst").
88
89 The destination may be a directory.
90
91 """
Guido van Rossuma2baf461997-04-29 14:06:46 +000092 if os.path.isdir(dst):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +000093 dst = os.path.join(dst, os.path.basename(src))
Guido van Rossuma2baf461997-04-29 14:06:46 +000094 copyfile(src, dst)
95 copystat(src, dst)
Guido van Rossumc6360141990-10-13 19:23:40 +000096
Georg Brandl2ee470f2008-07-16 12:55:28 +000097def ignore_patterns(*patterns):
98 """Function that can be used as copytree() ignore parameter.
Guido van Rossum9d0a3df1997-04-29 14:45:19 +000099
Georg Brandl2ee470f2008-07-16 12:55:28 +0000100 Patterns is a sequence of glob-style patterns
101 that are used to exclude files"""
102 def _ignore_patterns(path, names):
103 ignored_names = []
104 for pattern in patterns:
105 ignored_names.extend(fnmatch.filter(names, pattern))
106 return set(ignored_names)
107 return _ignore_patterns
108
109def copytree(src, dst, symlinks=False, ignore=None):
Guido van Rossum9d0a3df1997-04-29 14:45:19 +0000110 """Recursively copy a directory tree using copy2().
111
112 The destination directory must not already exist.
Neal Norwitza4c93b62003-02-23 21:36:32 +0000113 If exception(s) occur, an Error is raised with a list of reasons.
Guido van Rossum9d0a3df1997-04-29 14:45:19 +0000114
115 If the optional symlinks flag is true, symbolic links in the
116 source tree result in symbolic links in the destination tree; if
117 it is false, the contents of the files pointed to by symbolic
118 links are copied.
119
Georg Brandl2ee470f2008-07-16 12:55:28 +0000120 The optional ignore argument is a callable. If given, it
121 is called with the `src` parameter, which is the directory
122 being visited by copytree(), and `names` which is the list of
123 `src` contents, as returned by os.listdir():
124
125 callable(src, names) -> ignored_names
126
127 Since copytree() is called recursively, the callable will be
128 called once for each directory that is copied. It returns a
129 list of names relative to the `src` directory that should
130 not be copied.
131
Guido van Rossum9d0a3df1997-04-29 14:45:19 +0000132 XXX Consider this example code rather than the ultimate tool.
133
134 """
Guido van Rossuma2baf461997-04-29 14:06:46 +0000135 names = os.listdir(src)
Georg Brandl2ee470f2008-07-16 12:55:28 +0000136 if ignore is not None:
137 ignored_names = ignore(src, names)
138 else:
139 ignored_names = set()
140
Johannes Gijsberse4172ea2005-01-08 12:31:29 +0000141 os.makedirs(dst)
Martin v. Löwise9ce0b02002-10-07 13:23:24 +0000142 errors = []
Guido van Rossuma2baf461997-04-29 14:06:46 +0000143 for name in names:
Georg Brandl2ee470f2008-07-16 12:55:28 +0000144 if name in ignored_names:
145 continue
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000146 srcname = os.path.join(src, name)
147 dstname = os.path.join(dst, name)
148 try:
149 if symlinks and os.path.islink(srcname):
150 linkto = os.readlink(srcname)
151 os.symlink(linkto, dstname)
152 elif os.path.isdir(srcname):
Georg Brandl2ee470f2008-07-16 12:55:28 +0000153 copytree(srcname, dstname, symlinks, ignore)
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000154 else:
155 copy2(srcname, dstname)
156 # XXX What about devices, sockets etc.?
Guido van Rossumb940e112007-01-10 16:19:56 +0000157 except (IOError, os.error) as why:
Thomas Wouters477c8d52006-05-27 19:21:47 +0000158 errors.append((srcname, dstname, str(why)))
Georg Brandla1be88e2005-08-31 22:48:45 +0000159 # catch the Error from the recursive copytree so that we can
160 # continue with other files
Guido van Rossumb940e112007-01-10 16:19:56 +0000161 except Error as err:
Georg Brandla1be88e2005-08-31 22:48:45 +0000162 errors.extend(err.args[0])
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000163 try:
164 copystat(src, dst)
165 except WindowsError:
166 # can't copy file access times on Windows
167 pass
Guido van Rossumb940e112007-01-10 16:19:56 +0000168 except OSError as why:
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000169 errors.extend((src, dst, str(why)))
Martin v. Löwise9ce0b02002-10-07 13:23:24 +0000170 if errors:
Collin Winterce36ad82007-08-30 01:19:48 +0000171 raise Error(errors)
Guido van Rossumd7673291998-02-06 21:38:09 +0000172
Barry Warsaw234d9a92003-01-24 17:36:15 +0000173def rmtree(path, ignore_errors=False, onerror=None):
Guido van Rossumd7673291998-02-06 21:38:09 +0000174 """Recursively delete a directory tree.
175
Johannes Gijsbersef5ffc42004-10-31 12:05:31 +0000176 If ignore_errors is set, errors are ignored; otherwise, if onerror
177 is set, it is called to handle the error with arguments (func,
178 path, exc_info) where func is os.listdir, os.remove, or os.rmdir;
179 path is the argument to that function that caused it to fail; and
180 exc_info is a tuple returned by sys.exc_info(). If ignore_errors
181 is false and onerror is None, an exception is raised.
182
Guido van Rossumd7673291998-02-06 21:38:09 +0000183 """
Johannes Gijsbersef5ffc42004-10-31 12:05:31 +0000184 if ignore_errors:
185 def onerror(*args):
Barry Warsaw234d9a92003-01-24 17:36:15 +0000186 pass
Johannes Gijsbersef5ffc42004-10-31 12:05:31 +0000187 elif onerror is None:
188 def onerror(*args):
189 raise
Christian Heimes9bd667a2008-01-20 15:14:11 +0000190 try:
191 if os.path.islink(path):
192 # symlinks to directories are forbidden, see bug #1669
193 raise OSError("Cannot call rmtree on a symbolic link")
194 except OSError:
195 onerror(os.path.islink, path, sys.exc_info())
196 # can't continue even if onerror hook returns
197 return
Johannes Gijsbersef5ffc42004-10-31 12:05:31 +0000198 names = []
199 try:
200 names = os.listdir(path)
Guido van Rossumb940e112007-01-10 16:19:56 +0000201 except os.error as err:
Johannes Gijsbersef5ffc42004-10-31 12:05:31 +0000202 onerror(os.listdir, path, sys.exc_info())
203 for name in names:
204 fullname = os.path.join(path, name)
205 try:
206 mode = os.lstat(fullname).st_mode
207 except os.error:
208 mode = 0
209 if stat.S_ISDIR(mode):
210 rmtree(fullname, ignore_errors, onerror)
Barry Warsaw234d9a92003-01-24 17:36:15 +0000211 else:
Johannes Gijsbersef5ffc42004-10-31 12:05:31 +0000212 try:
213 os.remove(fullname)
Guido van Rossumb940e112007-01-10 16:19:56 +0000214 except os.error as err:
Johannes Gijsbersef5ffc42004-10-31 12:05:31 +0000215 onerror(os.remove, fullname, sys.exc_info())
216 try:
217 os.rmdir(path)
218 except os.error:
219 onerror(os.rmdir, path, sys.exc_info())
Guido van Rossumd7673291998-02-06 21:38:09 +0000220
Martin v. Löwise9ce0b02002-10-07 13:23:24 +0000221
Christian Heimesada8c3b2008-03-18 18:26:33 +0000222def _basename(path):
223 # A basename() variant which first strips the trailing slash, if present.
224 # Thus we always get the last component of the path, even for directories.
225 return os.path.basename(path.rstrip(os.path.sep))
226
227def move(src, dst):
228 """Recursively move a file or directory to another location. This is
229 similar to the Unix "mv" command.
230
231 If the destination is a directory or a symlink to a directory, the source
232 is moved inside the directory. The destination path must not already
233 exist.
234
235 If the destination already exists but is not a directory, it may be
236 overwritten depending on os.rename() semantics.
237
238 If the destination is on our current filesystem, then rename() is used.
239 Otherwise, src is copied to the destination and then removed.
Martin v. Löwise9ce0b02002-10-07 13:23:24 +0000240 A lot more could be done here... A look at a mv.c shows a lot of
241 the issues this implementation glosses over.
242
243 """
Christian Heimesada8c3b2008-03-18 18:26:33 +0000244 real_dst = dst
245 if os.path.isdir(dst):
246 real_dst = os.path.join(dst, _basename(src))
247 if os.path.exists(real_dst):
248 raise Error("Destination path '%s' already exists" % real_dst)
Martin v. Löwise9ce0b02002-10-07 13:23:24 +0000249 try:
Christian Heimesada8c3b2008-03-18 18:26:33 +0000250 os.rename(src, real_dst)
Martin v. Löwise9ce0b02002-10-07 13:23:24 +0000251 except OSError:
252 if os.path.isdir(src):
Brett Cannon1c3fa182004-06-19 21:11:35 +0000253 if destinsrc(src, dst):
Collin Winterce36ad82007-08-30 01:19:48 +0000254 raise Error("Cannot move a directory '%s' into itself '%s'." % (src, dst))
Christian Heimesada8c3b2008-03-18 18:26:33 +0000255 copytree(src, real_dst, symlinks=True)
Martin v. Löwise9ce0b02002-10-07 13:23:24 +0000256 rmtree(src)
257 else:
Christian Heimesada8c3b2008-03-18 18:26:33 +0000258 copy2(src, real_dst)
Martin v. Löwise9ce0b02002-10-07 13:23:24 +0000259 os.unlink(src)
Brett Cannon1c3fa182004-06-19 21:11:35 +0000260
261def destinsrc(src, dst):
262 return abspath(dst).startswith(abspath(src))