blob: c365ad6fe75002603661f7db3473a5daf1edfa56 [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
Guido van Rossumc6360141990-10-13 19:23:40 +000011
Skip Montanaro0de65802001-02-15 22:15:14 +000012__all__ = ["copyfileobj","copyfile","copymode","copystat","copy","copy2",
Raymond Hettinger2b9bfb32002-10-30 05:44:50 +000013 "copytree","move","rmtree","Error"]
Martin v. Löwise9ce0b02002-10-07 13:23:24 +000014
Neal Norwitz4ce69a52005-09-01 00:45:28 +000015class Error(EnvironmentError):
Martin v. Löwise9ce0b02002-10-07 13:23:24 +000016 pass
Guido van Rossumc6360141990-10-13 19:23:40 +000017
Greg Stein42bb8b32000-07-12 09:55:30 +000018def copyfileobj(fsrc, fdst, length=16*1024):
19 """copy data from file-like object fsrc to file-like object fdst"""
20 while 1:
21 buf = fsrc.read(length)
22 if not buf:
23 break
24 fdst.write(buf)
25
Johannes Gijsbers46f14592004-08-14 13:30:02 +000026def _samefile(src, dst):
27 # Macintosh, Unix.
28 if hasattr(os.path,'samefile'):
Johannes Gijsbersf9a098e2004-08-14 14:51:01 +000029 try:
30 return os.path.samefile(src, dst)
31 except OSError:
32 return False
Johannes Gijsbers46f14592004-08-14 13:30:02 +000033
34 # All other platforms: check for same pathname.
35 return (os.path.normcase(os.path.abspath(src)) ==
36 os.path.normcase(os.path.abspath(dst)))
Tim Peters495ad3c2001-01-15 01:36:40 +000037
Guido van Rossumc6360141990-10-13 19:23:40 +000038def copyfile(src, dst):
Guido van Rossum9d0a3df1997-04-29 14:45:19 +000039 """Copy data from src to dst"""
Johannes Gijsbers46f14592004-08-14 13:30:02 +000040 if _samefile(src, dst):
Collin Winterce36ad82007-08-30 01:19:48 +000041 raise Error("`%s` and `%s` are the same file" % (src, dst))
Johannes Gijsbers46f14592004-08-14 13:30:02 +000042
Guido van Rossuma2baf461997-04-29 14:06:46 +000043 fsrc = None
44 fdst = None
45 try:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +000046 fsrc = open(src, 'rb')
47 fdst = open(dst, 'wb')
Greg Stein42bb8b32000-07-12 09:55:30 +000048 copyfileobj(fsrc, fdst)
Guido van Rossuma2baf461997-04-29 14:06:46 +000049 finally:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +000050 if fdst:
51 fdst.close()
52 if fsrc:
53 fsrc.close()
Guido van Rossumc6360141990-10-13 19:23:40 +000054
Guido van Rossumc6360141990-10-13 19:23:40 +000055def copymode(src, dst):
Guido van Rossum9d0a3df1997-04-29 14:45:19 +000056 """Copy mode bits from src to dst"""
Tim Peters0c947242001-01-21 20:00:00 +000057 if hasattr(os, 'chmod'):
58 st = os.stat(src)
Walter Dörwald294bbf32002-06-06 09:48:13 +000059 mode = stat.S_IMODE(st.st_mode)
Tim Peters0c947242001-01-21 20:00:00 +000060 os.chmod(dst, mode)
Guido van Rossumc6360141990-10-13 19:23:40 +000061
Guido van Rossumc6360141990-10-13 19:23:40 +000062def copystat(src, dst):
Thomas Wouterscf297e42007-02-23 15:07:44 +000063 """Copy all stat info (mode bits, atime, mtime, flags) from src to dst"""
Guido van Rossuma2baf461997-04-29 14:06:46 +000064 st = os.stat(src)
Walter Dörwald294bbf32002-06-06 09:48:13 +000065 mode = stat.S_IMODE(st.st_mode)
Tim Peters0c947242001-01-21 20:00:00 +000066 if hasattr(os, 'utime'):
Walter Dörwald294bbf32002-06-06 09:48:13 +000067 os.utime(dst, (st.st_atime, st.st_mtime))
Tim Peters0c947242001-01-21 20:00:00 +000068 if hasattr(os, 'chmod'):
69 os.chmod(dst, mode)
Thomas Wouterscf297e42007-02-23 15:07:44 +000070 if hasattr(os, 'chflags') and hasattr(st, 'st_flags'):
71 os.chflags(dst, st.st_flags)
Guido van Rossumc6360141990-10-13 19:23:40 +000072
Guido van Rossum9d0a3df1997-04-29 14:45:19 +000073
Guido van Rossumc6360141990-10-13 19:23:40 +000074def copy(src, dst):
Guido van Rossum9d0a3df1997-04-29 14:45:19 +000075 """Copy data and mode bits ("cp src dst").
Tim Peters495ad3c2001-01-15 01:36:40 +000076
Guido van Rossum9d0a3df1997-04-29 14:45:19 +000077 The destination may be a directory.
78
79 """
Guido van Rossuma2baf461997-04-29 14:06:46 +000080 if os.path.isdir(dst):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +000081 dst = os.path.join(dst, os.path.basename(src))
Guido van Rossuma2baf461997-04-29 14:06:46 +000082 copyfile(src, dst)
83 copymode(src, dst)
Guido van Rossumc6360141990-10-13 19:23:40 +000084
Guido van Rossumc6360141990-10-13 19:23:40 +000085def copy2(src, dst):
Guido van Rossum9d0a3df1997-04-29 14:45:19 +000086 """Copy data and all stat info ("cp -p src dst").
87
88 The destination may be a directory.
89
90 """
Guido van Rossuma2baf461997-04-29 14:06:46 +000091 if os.path.isdir(dst):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +000092 dst = os.path.join(dst, os.path.basename(src))
Guido van Rossuma2baf461997-04-29 14:06:46 +000093 copyfile(src, dst)
94 copystat(src, dst)
Guido van Rossumc6360141990-10-13 19:23:40 +000095
Guido van Rossum9d0a3df1997-04-29 14:45:19 +000096
Neal Norwitza4c93b62003-02-23 21:36:32 +000097def copytree(src, dst, symlinks=False):
Guido van Rossum9d0a3df1997-04-29 14:45:19 +000098 """Recursively copy a directory tree using copy2().
99
100 The destination directory must not already exist.
Neal Norwitza4c93b62003-02-23 21:36:32 +0000101 If exception(s) occur, an Error is raised with a list of reasons.
Guido van Rossum9d0a3df1997-04-29 14:45:19 +0000102
103 If the optional symlinks flag is true, symbolic links in the
104 source tree result in symbolic links in the destination tree; if
105 it is false, the contents of the files pointed to by symbolic
106 links are copied.
107
108 XXX Consider this example code rather than the ultimate tool.
109
110 """
Guido van Rossuma2baf461997-04-29 14:06:46 +0000111 names = os.listdir(src)
Johannes Gijsberse4172ea2005-01-08 12:31:29 +0000112 os.makedirs(dst)
Martin v. Löwise9ce0b02002-10-07 13:23:24 +0000113 errors = []
Guido van Rossuma2baf461997-04-29 14:06:46 +0000114 for name in names:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000115 srcname = os.path.join(src, name)
116 dstname = os.path.join(dst, name)
117 try:
118 if symlinks and os.path.islink(srcname):
119 linkto = os.readlink(srcname)
120 os.symlink(linkto, dstname)
121 elif os.path.isdir(srcname):
Fred Drake5fa38862000-04-07 14:34:50 +0000122 copytree(srcname, dstname, symlinks)
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000123 else:
124 copy2(srcname, dstname)
125 # XXX What about devices, sockets etc.?
Guido van Rossumb940e112007-01-10 16:19:56 +0000126 except (IOError, os.error) as why:
Thomas Wouters477c8d52006-05-27 19:21:47 +0000127 errors.append((srcname, dstname, str(why)))
Georg Brandla1be88e2005-08-31 22:48:45 +0000128 # catch the Error from the recursive copytree so that we can
129 # continue with other files
Guido van Rossumb940e112007-01-10 16:19:56 +0000130 except Error as err:
Georg Brandla1be88e2005-08-31 22:48:45 +0000131 errors.extend(err.args[0])
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000132 try:
133 copystat(src, dst)
134 except WindowsError:
135 # can't copy file access times on Windows
136 pass
Guido van Rossumb940e112007-01-10 16:19:56 +0000137 except OSError as why:
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000138 errors.extend((src, dst, str(why)))
Martin v. Löwise9ce0b02002-10-07 13:23:24 +0000139 if errors:
Collin Winterce36ad82007-08-30 01:19:48 +0000140 raise Error(errors)
Guido van Rossumd7673291998-02-06 21:38:09 +0000141
Barry Warsaw234d9a92003-01-24 17:36:15 +0000142def rmtree(path, ignore_errors=False, onerror=None):
Guido van Rossumd7673291998-02-06 21:38:09 +0000143 """Recursively delete a directory tree.
144
Johannes Gijsbersef5ffc42004-10-31 12:05:31 +0000145 If ignore_errors is set, errors are ignored; otherwise, if onerror
146 is set, it is called to handle the error with arguments (func,
147 path, exc_info) where func is os.listdir, os.remove, or os.rmdir;
148 path is the argument to that function that caused it to fail; and
149 exc_info is a tuple returned by sys.exc_info(). If ignore_errors
150 is false and onerror is None, an exception is raised.
151
Guido van Rossumd7673291998-02-06 21:38:09 +0000152 """
Johannes Gijsbersef5ffc42004-10-31 12:05:31 +0000153 if ignore_errors:
154 def onerror(*args):
Barry Warsaw234d9a92003-01-24 17:36:15 +0000155 pass
Johannes Gijsbersef5ffc42004-10-31 12:05:31 +0000156 elif onerror is None:
157 def onerror(*args):
158 raise
Christian Heimes9bd667a2008-01-20 15:14:11 +0000159 try:
160 if os.path.islink(path):
161 # symlinks to directories are forbidden, see bug #1669
162 raise OSError("Cannot call rmtree on a symbolic link")
163 except OSError:
164 onerror(os.path.islink, path, sys.exc_info())
165 # can't continue even if onerror hook returns
166 return
Johannes Gijsbersef5ffc42004-10-31 12:05:31 +0000167 names = []
168 try:
169 names = os.listdir(path)
Guido van Rossumb940e112007-01-10 16:19:56 +0000170 except os.error as err:
Johannes Gijsbersef5ffc42004-10-31 12:05:31 +0000171 onerror(os.listdir, path, sys.exc_info())
172 for name in names:
173 fullname = os.path.join(path, name)
174 try:
175 mode = os.lstat(fullname).st_mode
176 except os.error:
177 mode = 0
178 if stat.S_ISDIR(mode):
179 rmtree(fullname, ignore_errors, onerror)
Barry Warsaw234d9a92003-01-24 17:36:15 +0000180 else:
Johannes Gijsbersef5ffc42004-10-31 12:05:31 +0000181 try:
182 os.remove(fullname)
Guido van Rossumb940e112007-01-10 16:19:56 +0000183 except os.error as err:
Johannes Gijsbersef5ffc42004-10-31 12:05:31 +0000184 onerror(os.remove, fullname, sys.exc_info())
185 try:
186 os.rmdir(path)
187 except os.error:
188 onerror(os.rmdir, path, sys.exc_info())
Guido van Rossumd7673291998-02-06 21:38:09 +0000189
Martin v. Löwise9ce0b02002-10-07 13:23:24 +0000190def move(src, dst):
191 """Recursively move a file or directory to another location.
192
193 If the destination is on our current filesystem, then simply use
194 rename. Otherwise, copy src to the dst and then remove src.
195 A lot more could be done here... A look at a mv.c shows a lot of
196 the issues this implementation glosses over.
197
198 """
199
200 try:
201 os.rename(src, dst)
202 except OSError:
203 if os.path.isdir(src):
Brett Cannon1c3fa182004-06-19 21:11:35 +0000204 if destinsrc(src, dst):
Collin Winterce36ad82007-08-30 01:19:48 +0000205 raise Error("Cannot move a directory '%s' into itself '%s'." % (src, dst))
Neal Norwitza4c93b62003-02-23 21:36:32 +0000206 copytree(src, dst, symlinks=True)
Martin v. Löwise9ce0b02002-10-07 13:23:24 +0000207 rmtree(src)
208 else:
209 copy2(src,dst)
210 os.unlink(src)
Brett Cannon1c3fa182004-06-19 21:11:35 +0000211
212def destinsrc(src, dst):
213 return abspath(dst).startswith(abspath(src))