blob: 6e3a27639e5adeefdfdd4e8c4c43b4dcade5f65e [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
Guido van Rossumc6360141990-10-13 19:23:40 +000010
Skip Montanaro0de65802001-02-15 22:15:14 +000011__all__ = ["copyfileobj","copyfile","copymode","copystat","copy","copy2",
12 "copytree","rmtree"]
Guido van Rossumc6360141990-10-13 19:23:40 +000013
Greg Stein42bb8b32000-07-12 09:55:30 +000014def copyfileobj(fsrc, fdst, length=16*1024):
15 """copy data from file-like object fsrc to file-like object fdst"""
16 while 1:
17 buf = fsrc.read(length)
18 if not buf:
19 break
20 fdst.write(buf)
21
Tim Peters495ad3c2001-01-15 01:36:40 +000022
Guido van Rossumc6360141990-10-13 19:23:40 +000023def copyfile(src, dst):
Guido van Rossum9d0a3df1997-04-29 14:45:19 +000024 """Copy data from src to dst"""
Guido van Rossuma2baf461997-04-29 14:06:46 +000025 fsrc = None
26 fdst = None
27 try:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +000028 fsrc = open(src, 'rb')
29 fdst = open(dst, 'wb')
Greg Stein42bb8b32000-07-12 09:55:30 +000030 copyfileobj(fsrc, fdst)
Guido van Rossuma2baf461997-04-29 14:06:46 +000031 finally:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +000032 if fdst:
33 fdst.close()
34 if fsrc:
35 fsrc.close()
Guido van Rossumc6360141990-10-13 19:23:40 +000036
Guido van Rossumc6360141990-10-13 19:23:40 +000037def copymode(src, dst):
Guido van Rossum9d0a3df1997-04-29 14:45:19 +000038 """Copy mode bits from src to dst"""
Tim Peters0c947242001-01-21 20:00:00 +000039 if hasattr(os, 'chmod'):
40 st = os.stat(src)
41 mode = stat.S_IMODE(st[stat.ST_MODE])
42 os.chmod(dst, mode)
Guido van Rossumc6360141990-10-13 19:23:40 +000043
Guido van Rossumc6360141990-10-13 19:23:40 +000044def copystat(src, dst):
Guido van Rossum9d0a3df1997-04-29 14:45:19 +000045 """Copy all stat info (mode bits, atime and mtime) from src to dst"""
Guido van Rossuma2baf461997-04-29 14:06:46 +000046 st = os.stat(src)
Guido van Rossum9d0a3df1997-04-29 14:45:19 +000047 mode = stat.S_IMODE(st[stat.ST_MODE])
Tim Peters0c947242001-01-21 20:00:00 +000048 if hasattr(os, 'utime'):
49 os.utime(dst, (st[stat.ST_ATIME], st[stat.ST_MTIME]))
50 if hasattr(os, 'chmod'):
51 os.chmod(dst, mode)
Guido van Rossumc6360141990-10-13 19:23:40 +000052
Guido van Rossum9d0a3df1997-04-29 14:45:19 +000053
Guido van Rossumc6360141990-10-13 19:23:40 +000054def copy(src, dst):
Guido van Rossum9d0a3df1997-04-29 14:45:19 +000055 """Copy data and mode bits ("cp src dst").
Tim Peters495ad3c2001-01-15 01:36:40 +000056
Guido van Rossum9d0a3df1997-04-29 14:45:19 +000057 The destination may be a directory.
58
59 """
Guido van Rossuma2baf461997-04-29 14:06:46 +000060 if os.path.isdir(dst):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +000061 dst = os.path.join(dst, os.path.basename(src))
Guido van Rossuma2baf461997-04-29 14:06:46 +000062 copyfile(src, dst)
63 copymode(src, dst)
Guido van Rossumc6360141990-10-13 19:23:40 +000064
Guido van Rossumc6360141990-10-13 19:23:40 +000065def copy2(src, dst):
Guido van Rossum9d0a3df1997-04-29 14:45:19 +000066 """Copy data and all stat info ("cp -p src dst").
67
68 The destination may be a directory.
69
70 """
Guido van Rossuma2baf461997-04-29 14:06:46 +000071 if os.path.isdir(dst):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +000072 dst = os.path.join(dst, os.path.basename(src))
Guido van Rossuma2baf461997-04-29 14:06:46 +000073 copyfile(src, dst)
74 copystat(src, dst)
Guido van Rossumc6360141990-10-13 19:23:40 +000075
Guido van Rossum9d0a3df1997-04-29 14:45:19 +000076
77def copytree(src, dst, symlinks=0):
78 """Recursively copy a directory tree using copy2().
79
80 The destination directory must not already exist.
81 Error are reported to standard output.
82
83 If the optional symlinks flag is true, symbolic links in the
84 source tree result in symbolic links in the destination tree; if
85 it is false, the contents of the files pointed to by symbolic
86 links are copied.
87
88 XXX Consider this example code rather than the ultimate tool.
89
90 """
Guido van Rossuma2baf461997-04-29 14:06:46 +000091 names = os.listdir(src)
Guido van Rossum9d0a3df1997-04-29 14:45:19 +000092 os.mkdir(dst)
Guido van Rossuma2baf461997-04-29 14:06:46 +000093 for name in names:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +000094 srcname = os.path.join(src, name)
95 dstname = os.path.join(dst, name)
96 try:
97 if symlinks and os.path.islink(srcname):
98 linkto = os.readlink(srcname)
99 os.symlink(linkto, dstname)
100 elif os.path.isdir(srcname):
Fred Drake5fa38862000-04-07 14:34:50 +0000101 copytree(srcname, dstname, symlinks)
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000102 else:
103 copy2(srcname, dstname)
104 # XXX What about devices, sockets etc.?
105 except (IOError, os.error), why:
106 print "Can't copy %s to %s: %s" % (`srcname`, `dstname`, str(why))
Guido van Rossumd7673291998-02-06 21:38:09 +0000107
108def rmtree(path, ignore_errors=0, onerror=None):
109 """Recursively delete a directory tree.
110
111 If ignore_errors is set, errors are ignored; otherwise, if
112 onerror is set, it is called to handle the error; otherwise, an
113 exception is raised.
114
115 """
116 cmdtuples = []
117 _build_cmdtuple(path, cmdtuples)
118 for cmd in cmdtuples:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000119 try:
120 apply(cmd[0], (cmd[1],))
121 except:
122 exc = sys.exc_info()
123 if ignore_errors:
124 pass
125 elif onerror:
126 onerror(cmd[0], cmd[1], exc)
127 else:
128 raise exc[0], (exc[1][0], exc[1][1] + ' removing '+cmd[1])
Guido van Rossumd7673291998-02-06 21:38:09 +0000129
130# Helper for rmtree()
131def _build_cmdtuple(path, cmdtuples):
132 for f in os.listdir(path):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000133 real_f = os.path.join(path,f)
134 if os.path.isdir(real_f) and not os.path.islink(real_f):
135 _build_cmdtuple(real_f, cmdtuples)
136 else:
Guido van Rossumd832f9e1998-10-07 13:18:17 +0000137 cmdtuples.append((os.remove, real_f))
138 cmdtuples.append((os.rmdir, path))