blob: f30ba86483cd063e2122d51a014a12e4df3f45c8 [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
Georg Brandl1576bab2008-08-12 08:39:33 +000018try:
19 WindowsError
20except NameError:
21 WindowsError = None
22
Greg Stein42bb8b32000-07-12 09:55:30 +000023def copyfileobj(fsrc, fdst, length=16*1024):
24 """copy data from file-like object fsrc to file-like object fdst"""
25 while 1:
26 buf = fsrc.read(length)
27 if not buf:
28 break
29 fdst.write(buf)
30
Johannes Gijsbers46f14592004-08-14 13:30:02 +000031def _samefile(src, dst):
32 # Macintosh, Unix.
33 if hasattr(os.path,'samefile'):
Johannes Gijsbersf9a098e2004-08-14 14:51:01 +000034 try:
35 return os.path.samefile(src, dst)
36 except OSError:
37 return False
Johannes Gijsbers46f14592004-08-14 13:30:02 +000038
39 # All other platforms: check for same pathname.
40 return (os.path.normcase(os.path.abspath(src)) ==
41 os.path.normcase(os.path.abspath(dst)))
Tim Peters495ad3c2001-01-15 01:36:40 +000042
Guido van Rossumc6360141990-10-13 19:23:40 +000043def copyfile(src, dst):
Guido van Rossum9d0a3df1997-04-29 14:45:19 +000044 """Copy data from src to dst"""
Johannes Gijsbers46f14592004-08-14 13:30:02 +000045 if _samefile(src, dst):
46 raise Error, "`%s` and `%s` are the same file" % (src, dst)
47
Guido van Rossuma2baf461997-04-29 14:06:46 +000048 fsrc = None
49 fdst = None
50 try:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +000051 fsrc = open(src, 'rb')
52 fdst = open(dst, 'wb')
Greg Stein42bb8b32000-07-12 09:55:30 +000053 copyfileobj(fsrc, fdst)
Guido van Rossuma2baf461997-04-29 14:06:46 +000054 finally:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +000055 if fdst:
56 fdst.close()
57 if fsrc:
58 fsrc.close()
Guido van Rossumc6360141990-10-13 19:23:40 +000059
Guido van Rossumc6360141990-10-13 19:23:40 +000060def copymode(src, dst):
Guido van Rossum9d0a3df1997-04-29 14:45:19 +000061 """Copy mode bits from src to dst"""
Tim Peters0c947242001-01-21 20:00:00 +000062 if hasattr(os, 'chmod'):
63 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 os.chmod(dst, mode)
Guido van Rossumc6360141990-10-13 19:23:40 +000066
Guido van Rossumc6360141990-10-13 19:23:40 +000067def copystat(src, dst):
Guido van Rossum9d0a3df1997-04-29 14:45:19 +000068 """Copy all stat info (mode bits, atime and mtime) from src to dst"""
Guido van Rossuma2baf461997-04-29 14:06:46 +000069 st = os.stat(src)
Walter Dörwald294bbf32002-06-06 09:48:13 +000070 mode = stat.S_IMODE(st.st_mode)
Tim Peters0c947242001-01-21 20:00:00 +000071 if hasattr(os, 'utime'):
Walter Dörwald294bbf32002-06-06 09:48:13 +000072 os.utime(dst, (st.st_atime, st.st_mtime))
Tim Peters0c947242001-01-21 20:00:00 +000073 if hasattr(os, 'chmod'):
74 os.chmod(dst, mode)
Guido van Rossumc6360141990-10-13 19:23:40 +000075
Guido van Rossum9d0a3df1997-04-29 14:45:19 +000076
Guido van Rossumc6360141990-10-13 19:23:40 +000077def copy(src, dst):
Guido van Rossum9d0a3df1997-04-29 14:45:19 +000078 """Copy data and mode bits ("cp src dst").
Tim Peters495ad3c2001-01-15 01:36:40 +000079
Guido van Rossum9d0a3df1997-04-29 14:45:19 +000080 The destination may be a directory.
81
82 """
Guido van Rossuma2baf461997-04-29 14:06:46 +000083 if os.path.isdir(dst):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +000084 dst = os.path.join(dst, os.path.basename(src))
Guido van Rossuma2baf461997-04-29 14:06:46 +000085 copyfile(src, dst)
86 copymode(src, dst)
Guido van Rossumc6360141990-10-13 19:23:40 +000087
Guido van Rossumc6360141990-10-13 19:23:40 +000088def copy2(src, dst):
Guido van Rossum9d0a3df1997-04-29 14:45:19 +000089 """Copy data and all stat info ("cp -p src dst").
90
91 The destination may be a directory.
92
93 """
Guido van Rossuma2baf461997-04-29 14:06:46 +000094 if os.path.isdir(dst):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +000095 dst = os.path.join(dst, os.path.basename(src))
Guido van Rossuma2baf461997-04-29 14:06:46 +000096 copyfile(src, dst)
97 copystat(src, dst)
Guido van Rossumc6360141990-10-13 19:23:40 +000098
Guido van Rossum9d0a3df1997-04-29 14:45:19 +000099
Neal Norwitza4c93b62003-02-23 21:36:32 +0000100def copytree(src, dst, symlinks=False):
Guido van Rossum9d0a3df1997-04-29 14:45:19 +0000101 """Recursively copy a directory tree using copy2().
102
103 The destination directory must not already exist.
Neal Norwitza4c93b62003-02-23 21:36:32 +0000104 If exception(s) occur, an Error is raised with a list of reasons.
Guido van Rossum9d0a3df1997-04-29 14:45:19 +0000105
106 If the optional symlinks flag is true, symbolic links in the
107 source tree result in symbolic links in the destination tree; if
108 it is false, the contents of the files pointed to by symbolic
109 links are copied.
110
111 XXX Consider this example code rather than the ultimate tool.
112
113 """
Guido van Rossuma2baf461997-04-29 14:06:46 +0000114 names = os.listdir(src)
Johannes Gijsberse4172ea2005-01-08 12:31:29 +0000115 os.makedirs(dst)
Martin v. Löwise9ce0b02002-10-07 13:23:24 +0000116 errors = []
Guido van Rossuma2baf461997-04-29 14:06:46 +0000117 for name in names:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000118 srcname = os.path.join(src, name)
119 dstname = os.path.join(dst, name)
120 try:
121 if symlinks and os.path.islink(srcname):
122 linkto = os.readlink(srcname)
123 os.symlink(linkto, dstname)
124 elif os.path.isdir(srcname):
Fred Drake5fa38862000-04-07 14:34:50 +0000125 copytree(srcname, dstname, symlinks)
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000126 else:
127 copy2(srcname, dstname)
128 # XXX What about devices, sockets etc.?
129 except (IOError, os.error), why:
Georg Brandl7a3fd892006-04-28 16:54:25 +0000130 errors.append((srcname, dstname, str(why)))
Georg Brandla1be88e2005-08-31 22:48:45 +0000131 # catch the Error from the recursive copytree so that we can
132 # continue with other files
133 except Error, err:
134 errors.extend(err.args[0])
Martin v. Löwis4e678382006-07-30 13:00:31 +0000135 try:
136 copystat(src, dst)
Martin v. Löwis4e678382006-07-30 13:00:31 +0000137 except OSError, why:
Georg Brandl1576bab2008-08-12 08:39:33 +0000138 if WindowsError is not None and isinstance(why, WindowsError):
139 # Copying file access times may fail on Windows
140 pass
141 else:
142 errors.extend((src, dst, str(why)))
Martin v. Löwise9ce0b02002-10-07 13:23:24 +0000143 if errors:
144 raise Error, errors
Guido van Rossumd7673291998-02-06 21:38:09 +0000145
Barry Warsaw234d9a92003-01-24 17:36:15 +0000146def rmtree(path, ignore_errors=False, onerror=None):
Guido van Rossumd7673291998-02-06 21:38:09 +0000147 """Recursively delete a directory tree.
148
Johannes Gijsbersef5ffc42004-10-31 12:05:31 +0000149 If ignore_errors is set, errors are ignored; otherwise, if onerror
150 is set, it is called to handle the error with arguments (func,
151 path, exc_info) where func is os.listdir, os.remove, or os.rmdir;
152 path is the argument to that function that caused it to fail; and
153 exc_info is a tuple returned by sys.exc_info(). If ignore_errors
154 is false and onerror is None, an exception is raised.
155
Guido van Rossumd7673291998-02-06 21:38:09 +0000156 """
Johannes Gijsbersef5ffc42004-10-31 12:05:31 +0000157 if ignore_errors:
158 def onerror(*args):
Barry Warsaw234d9a92003-01-24 17:36:15 +0000159 pass
Johannes Gijsbersef5ffc42004-10-31 12:05:31 +0000160 elif onerror is None:
161 def onerror(*args):
162 raise
163 names = []
164 try:
165 names = os.listdir(path)
166 except os.error, err:
167 onerror(os.listdir, path, sys.exc_info())
168 for name in names:
169 fullname = os.path.join(path, name)
170 try:
171 mode = os.lstat(fullname).st_mode
172 except os.error:
173 mode = 0
174 if stat.S_ISDIR(mode):
175 rmtree(fullname, ignore_errors, onerror)
Barry Warsaw234d9a92003-01-24 17:36:15 +0000176 else:
Johannes Gijsbersef5ffc42004-10-31 12:05:31 +0000177 try:
178 os.remove(fullname)
179 except os.error, err:
180 onerror(os.remove, fullname, sys.exc_info())
181 try:
182 os.rmdir(path)
183 except os.error:
184 onerror(os.rmdir, path, sys.exc_info())
Guido van Rossumd7673291998-02-06 21:38:09 +0000185
Martin v. Löwise9ce0b02002-10-07 13:23:24 +0000186def move(src, dst):
187 """Recursively move a file or directory to another location.
188
189 If the destination is on our current filesystem, then simply use
190 rename. Otherwise, copy src to the dst and then remove src.
191 A lot more could be done here... A look at a mv.c shows a lot of
192 the issues this implementation glosses over.
193
194 """
195
196 try:
197 os.rename(src, dst)
198 except OSError:
199 if os.path.isdir(src):
Brett Cannon1c3fa182004-06-19 21:11:35 +0000200 if destinsrc(src, dst):
201 raise Error, "Cannot move a directory '%s' into itself '%s'." % (src, dst)
Neal Norwitza4c93b62003-02-23 21:36:32 +0000202 copytree(src, dst, symlinks=True)
Martin v. Löwise9ce0b02002-10-07 13:23:24 +0000203 rmtree(src)
204 else:
205 copy2(src,dst)
206 os.unlink(src)
Brett Cannon1c3fa182004-06-19 21:11:35 +0000207
208def destinsrc(src, dst):
209 return abspath(dst).startswith(abspath(src))