blob: ed8a2ddf4fa0c6f449e2d040674786ed698d6369 [file] [log] [blame]
Guido van Rossum15e22e11997-12-05 19:03:01 +00001# Module 'ntpath' -- common operations on WinNT/Win95 pathnames
Tim Peters2344fae2001-01-15 00:50:52 +00002"""Common pathname manipulations, WindowsNT/95 version.
Guido van Rossum534972b1999-02-03 17:20:50 +00003
4Instead of importing this module directly, import os and refer to this
5module as os.path.
Guido van Rossum15e22e11997-12-05 19:03:01 +00006"""
Guido van Rossum555915a1994-02-24 11:32:59 +00007
8import os
9import stat
Skip Montanaro4d5d5bf2000-07-13 01:01:03 +000010
Skip Montanaro269b83b2001-02-06 01:07:02 +000011__all__ = ["normcase","isabs","join","splitdrive","split","splitext",
12 "basename","dirname","commonprefix","getsize","getmtime",
13 "getatime","islink","exists","isdir","isfile","ismount",
14 "walk","expanduser","expandvars","normpath","abspath","splitunc"]
Guido van Rossum555915a1994-02-24 11:32:59 +000015
Guido van Rossume2ad88c1997-08-12 14:46:58 +000016# Normalize the case of a pathname and map slashes to backslashes.
17# Other normalizations (such as optimizing '../' away) are not done
Guido van Rossum555915a1994-02-24 11:32:59 +000018# (this is done by normpath).
Guido van Rossume2ad88c1997-08-12 14:46:58 +000019
Guido van Rossum555915a1994-02-24 11:32:59 +000020def normcase(s):
Guido van Rossum16a0bc21998-02-18 13:48:31 +000021 """Normalize case of pathname.
22
Guido van Rossum534972b1999-02-03 17:20:50 +000023 Makes all characters lowercase and all slashes into backslashes."""
Fred Drakeb4e460a2000-09-28 16:25:20 +000024 return s.replace("/", "\\").lower()
Guido van Rossum555915a1994-02-24 11:32:59 +000025
Guido van Rossum77e1db31997-06-02 23:11:57 +000026
Fred Drakeef0b5dd2000-02-17 17:30:40 +000027# Return whether a path is absolute.
Guido van Rossum555915a1994-02-24 11:32:59 +000028# Trivial in Posix, harder on the Mac or MS-DOS.
29# For DOS it is absolute if it starts with a slash or backslash (current
Guido van Rossum534972b1999-02-03 17:20:50 +000030# volume), or if a pathname after the volume letter and colon / UNC resource
31# starts with a slash or backslash.
Guido van Rossum555915a1994-02-24 11:32:59 +000032
33def isabs(s):
Guido van Rossum15e22e11997-12-05 19:03:01 +000034 """Test whether a path is absolute"""
35 s = splitdrive(s)[1]
36 return s != '' and s[:1] in '/\\'
Guido van Rossum555915a1994-02-24 11:32:59 +000037
38
Guido van Rossum77e1db31997-06-02 23:11:57 +000039# Join two (or more) paths.
40
Barry Warsaw384d2491997-02-18 21:53:25 +000041def join(a, *p):
Guido van Rossum15e22e11997-12-05 19:03:01 +000042 """Join two or more pathname components, inserting "\\" as needed"""
43 path = a
44 for b in p:
Tim Peters33dc0a12001-07-27 08:09:54 +000045 b_wins = 0 # set to 1 iff b makes path irrelevant
46 if path == "":
47 b_wins = 1
Tim Peters1bdd0f22001-07-19 17:18:18 +000048
Tim Peters33dc0a12001-07-27 08:09:54 +000049 elif isabs(b):
50 # This probably wipes out path so far. However, it's more
51 # complicated if path begins with a drive letter:
52 # 1. join('c:', '/a') == 'c:/a'
53 # 2. join('c:/', '/a') == 'c:/a'
54 # But
55 # 3. join('c:/a', '/b') == '/b'
56 # 4. join('c:', 'd:/') = 'd:/'
57 # 5. join('c:/', 'd:/') = 'd:/'
58 if path[1:2] != ":" or b[1:2] == ":":
59 # Path doesn't start with a drive letter, or cases 4 and 5.
60 b_wins = 1
Tim Peters1bdd0f22001-07-19 17:18:18 +000061
Tim Peters33dc0a12001-07-27 08:09:54 +000062 # Else path has a drive letter, and b doesn't but is absolute.
63 elif len(path) > 3 or (len(path) == 3 and
64 path[-1] not in "/\\"):
65 # case 3
66 b_wins = 1
Tim Peters1bdd0f22001-07-19 17:18:18 +000067
Tim Peters33dc0a12001-07-27 08:09:54 +000068 if b_wins:
69 path = b
70 else:
71 # Join, and ensure there's a separator.
72 assert len(path) > 0
73 if path[-1] in "/\\":
74 if b and b[0] in "/\\":
75 path += b[1:]
76 else:
77 path += b
78 elif path[-1] == ":":
79 path += b
80 elif b:
81 if b[0] in "/\\":
82 path += b
83 else:
84 path += "\\" + b
Tim Peters1bdd0f22001-07-19 17:18:18 +000085
Guido van Rossum15e22e11997-12-05 19:03:01 +000086 return path
Guido van Rossum555915a1994-02-24 11:32:59 +000087
88
89# Split a path in a drive specification (a drive letter followed by a
Guido van Rossumf3c695c1999-04-06 19:32:19 +000090# colon) and the path specification.
Guido van Rossum555915a1994-02-24 11:32:59 +000091# It is always true that drivespec + pathspec == p
92def splitdrive(p):
Guido van Rossumf3c695c1999-04-06 19:32:19 +000093 """Split a pathname into drive and path specifiers. Returns a 2-tuple
94"(drive,path)"; either part may be empty"""
Guido van Rossum15e22e11997-12-05 19:03:01 +000095 if p[1:2] == ':':
96 return p[0:2], p[2:]
Guido van Rossumf3c695c1999-04-06 19:32:19 +000097 return '', p
98
99
100# Parse UNC paths
101def splitunc(p):
102 """Split a pathname into UNC mount point and relative path specifiers.
103
104 Return a 2-tuple (unc, rest); either part may be empty.
105 If unc is not empty, it has the form '//host/mount' (or similar
106 using backslashes). unc+rest is always the input path.
107 Paths containing drive letters never have an UNC part.
108 """
109 if p[1:2] == ':':
110 return '', p # Drive letter present
Guido van Rossum534972b1999-02-03 17:20:50 +0000111 firstTwo = p[0:2]
112 if firstTwo == '//' or firstTwo == '\\\\':
113 # is a UNC path:
114 # vvvvvvvvvvvvvvvvvvvv equivalent to drive letter
115 # \\machine\mountpoint\directories...
116 # directory ^^^^^^^^^^^^^^^
117 normp = normcase(p)
Fred Drakeb4e460a2000-09-28 16:25:20 +0000118 index = normp.find('\\', 2)
Guido van Rossum534972b1999-02-03 17:20:50 +0000119 if index == -1:
120 ##raise RuntimeError, 'illegal UNC path: "' + p + '"'
121 return ("", p)
Fred Drakeb4e460a2000-09-28 16:25:20 +0000122 index = normp.find('\\', index + 1)
Guido van Rossum534972b1999-02-03 17:20:50 +0000123 if index == -1:
124 index = len(p)
125 return p[:index], p[index:]
Guido van Rossum15e22e11997-12-05 19:03:01 +0000126 return '', p
Guido van Rossum555915a1994-02-24 11:32:59 +0000127
128
129# Split a path in head (everything up to the last '/') and tail (the
Guido van Rossum8f0fa9e1999-03-19 21:05:12 +0000130# rest). After the trailing '/' is stripped, the invariant
Guido van Rossum555915a1994-02-24 11:32:59 +0000131# join(head, tail) == p holds.
132# The resulting head won't end in '/' unless it is the root.
133
134def split(p):
Guido van Rossum534972b1999-02-03 17:20:50 +0000135 """Split a pathname.
136
137 Return tuple (head, tail) where tail is everything after the final slash.
138 Either part may be empty."""
Guido van Rossum8f0fa9e1999-03-19 21:05:12 +0000139
Guido van Rossum15e22e11997-12-05 19:03:01 +0000140 d, p = splitdrive(p)
Guido van Rossum8f0fa9e1999-03-19 21:05:12 +0000141 # set i to index beyond p's last slash
142 i = len(p)
143 while i and p[i-1] not in '/\\':
144 i = i - 1
145 head, tail = p[:i], p[i:] # now tail has no slashes
146 # remove trailing slashes from head, unless it's all slashes
147 head2 = head
148 while head2 and head2[-1] in '/\\':
149 head2 = head2[:-1]
150 head = head2 or head
Guido van Rossum15e22e11997-12-05 19:03:01 +0000151 return d + head, tail
Guido van Rossum555915a1994-02-24 11:32:59 +0000152
153
154# Split a path in root and extension.
Guido van Rossum73e122f1997-01-22 00:17:26 +0000155# The extension is everything starting at the last dot in the last
Guido van Rossum555915a1994-02-24 11:32:59 +0000156# pathname component; the root is everything before that.
157# It is always true that root + ext == p.
158
159def splitext(p):
Guido van Rossum534972b1999-02-03 17:20:50 +0000160 """Split the extension from a pathname.
161
162 Extension is everything from the last dot to the end.
163 Return (root, ext), either part may be empty."""
Guido van Rossum15e22e11997-12-05 19:03:01 +0000164 root, ext = '', ''
165 for c in p:
166 if c in ['/','\\']:
167 root, ext = root + ext + c, ''
168 elif c == '.':
169 if ext:
170 root, ext = root + ext, c
171 else:
172 ext = c
173 elif ext:
174 ext = ext + c
175 else:
176 root = root + c
177 return root, ext
Guido van Rossum555915a1994-02-24 11:32:59 +0000178
179
180# Return the tail (basename) part of a path.
181
182def basename(p):
Guido van Rossum15e22e11997-12-05 19:03:01 +0000183 """Returns the final component of a pathname"""
184 return split(p)[1]
Guido van Rossum555915a1994-02-24 11:32:59 +0000185
186
187# Return the head (dirname) part of a path.
188
189def dirname(p):
Guido van Rossum15e22e11997-12-05 19:03:01 +0000190 """Returns the directory component of a pathname"""
191 return split(p)[0]
Guido van Rossum555915a1994-02-24 11:32:59 +0000192
193
194# Return the longest prefix of all list elements.
195
196def commonprefix(m):
Guido van Rossum15e22e11997-12-05 19:03:01 +0000197 "Given a list of pathnames, returns the longest common leading component"
198 if not m: return ''
Skip Montanaro62358312000-08-22 13:01:53 +0000199 prefix = m[0]
200 for item in m:
Guido van Rossum15e22e11997-12-05 19:03:01 +0000201 for i in range(len(prefix)):
Fred Drake8152d322000-12-12 23:20:45 +0000202 if prefix[:i+1] != item[:i+1]:
Guido van Rossum15e22e11997-12-05 19:03:01 +0000203 prefix = prefix[:i]
204 if i == 0: return ''
205 break
Skip Montanaro62358312000-08-22 13:01:53 +0000206 return prefix
Guido van Rossum555915a1994-02-24 11:32:59 +0000207
208
Guido van Rossum2bc1f8f1998-07-24 20:49:26 +0000209# Get size, mtime, atime of files.
210
211def getsize(filename):
Guido van Rossum534972b1999-02-03 17:20:50 +0000212 """Return the size of a file, reported by os.stat()"""
Guido van Rossum2bc1f8f1998-07-24 20:49:26 +0000213 st = os.stat(filename)
214 return st[stat.ST_SIZE]
215
216def getmtime(filename):
Guido van Rossum534972b1999-02-03 17:20:50 +0000217 """Return the last modification time of a file, reported by os.stat()"""
Guido van Rossum2bc1f8f1998-07-24 20:49:26 +0000218 st = os.stat(filename)
219 return st[stat.ST_MTIME]
220
221def getatime(filename):
Guido van Rossum534972b1999-02-03 17:20:50 +0000222 """Return the last access time of a file, reported by os.stat()"""
Guido van Rossum2bc1f8f1998-07-24 20:49:26 +0000223 st = os.stat(filename)
Fred Drake162bd852000-07-01 06:36:51 +0000224 return st[stat.ST_ATIME]
Guido van Rossum2bc1f8f1998-07-24 20:49:26 +0000225
226
Guido van Rossum555915a1994-02-24 11:32:59 +0000227# Is a path a symbolic link?
228# This will always return false on systems where posix.lstat doesn't exist.
229
230def islink(path):
Guido van Rossum15e22e11997-12-05 19:03:01 +0000231 """Test for symbolic link. On WindowsNT/95 always returns false"""
232 return 0
Guido van Rossum555915a1994-02-24 11:32:59 +0000233
234
235# Does a path exist?
236# This is false for dangling symbolic links.
237
238def exists(path):
Guido van Rossum15e22e11997-12-05 19:03:01 +0000239 """Test whether a path exists"""
240 try:
241 st = os.stat(path)
242 except os.error:
243 return 0
244 return 1
Guido van Rossum555915a1994-02-24 11:32:59 +0000245
246
247# Is a path a dos directory?
248# This follows symbolic links, so both islink() and isdir() can be true
249# for the same path.
250
251def isdir(path):
Guido van Rossum15e22e11997-12-05 19:03:01 +0000252 """Test whether a path is a directory"""
253 try:
254 st = os.stat(path)
255 except os.error:
256 return 0
257 return stat.S_ISDIR(st[stat.ST_MODE])
Guido van Rossum555915a1994-02-24 11:32:59 +0000258
259
260# Is a path a regular file?
261# This follows symbolic links, so both islink() and isdir() can be true
262# for the same path.
263
264def isfile(path):
Guido van Rossum15e22e11997-12-05 19:03:01 +0000265 """Test whether a path is a regular file"""
266 try:
267 st = os.stat(path)
268 except os.error:
269 return 0
270 return stat.S_ISREG(st[stat.ST_MODE])
Guido van Rossum555915a1994-02-24 11:32:59 +0000271
272
Guido van Rossumf3c695c1999-04-06 19:32:19 +0000273# Is a path a mount point? Either a root (with or without drive letter)
274# or an UNC path with at most a / or \ after the mount point.
Guido van Rossum555915a1994-02-24 11:32:59 +0000275
276def ismount(path):
Guido van Rossumca99c2c1998-01-19 22:25:59 +0000277 """Test whether a path is a mount point (defined as root of drive)"""
Guido van Rossumf3c695c1999-04-06 19:32:19 +0000278 unc, rest = splitunc(path)
279 if unc:
280 return rest in ("", "/", "\\")
Guido van Rossumca99c2c1998-01-19 22:25:59 +0000281 p = splitdrive(path)[1]
Fred Drakeb4e460a2000-09-28 16:25:20 +0000282 return len(p) == 1 and p[0] in '/\\'
Guido van Rossum555915a1994-02-24 11:32:59 +0000283
284
285# Directory tree walk.
286# For each directory under top (including top itself, but excluding
287# '.' and '..'), func(arg, dirname, filenames) is called, where
288# dirname is the name of the directory and filenames is the list
289# files files (and subdirectories etc.) in the directory.
290# The func may modify the filenames list, to implement a filter,
291# or to impose a different order of visiting.
292
293def walk(top, func, arg):
Tim Peterscf5e6a42001-10-10 04:16:20 +0000294 """Directory tree walk with callback function.
Guido van Rossum534972b1999-02-03 17:20:50 +0000295
Tim Peterscf5e6a42001-10-10 04:16:20 +0000296 For each directory in the directory tree rooted at top (including top
297 itself, but excluding '.' and '..'), call func(arg, dirname, fnames).
298 dirname is the name of the directory, and fnames a list of the names of
299 the files and subdirectories in dirname (excluding '.' and '..'). func
300 may modify the fnames list in-place (e.g. via del or slice assignment),
301 and walk will only recurse into the subdirectories whose names remain in
302 fnames; this can be used to implement a filter, or to impose a specific
303 order of visiting. No semantics are defined for, or required of, arg,
304 beyond that arg is always passed to func. It can be used, e.g., to pass
305 a filename pattern, or a mutable object designed to accumulate
306 statistics. Passing None for arg is common."""
307
Guido van Rossum15e22e11997-12-05 19:03:01 +0000308 try:
309 names = os.listdir(top)
310 except os.error:
311 return
312 func(arg, top, names)
313 exceptions = ('.', '..')
314 for name in names:
315 if name not in exceptions:
316 name = join(top, name)
317 if isdir(name):
318 walk(name, func, arg)
Guido van Rossum555915a1994-02-24 11:32:59 +0000319
320
321# Expand paths beginning with '~' or '~user'.
322# '~' means $HOME; '~user' means that user's home directory.
323# If the path doesn't begin with '~', or if the user or $HOME is unknown,
324# the path is returned unchanged (leaving error reporting to whatever
325# function is called with the expanded path as argument).
326# See also module 'glob' for expansion of *, ? and [...] in pathnames.
327# (A function should also be defined to do full *sh-style environment
328# variable expansion.)
329
330def expanduser(path):
Guido van Rossum534972b1999-02-03 17:20:50 +0000331 """Expand ~ and ~user constructs.
332
333 If user or $HOME is unknown, do nothing."""
Fred Drake8152d322000-12-12 23:20:45 +0000334 if path[:1] != '~':
Guido van Rossum15e22e11997-12-05 19:03:01 +0000335 return path
336 i, n = 1, len(path)
337 while i < n and path[i] not in '/\\':
Fred Drakeb4e460a2000-09-28 16:25:20 +0000338 i = i + 1
Guido van Rossum15e22e11997-12-05 19:03:01 +0000339 if i == 1:
340 if os.environ.has_key('HOME'):
341 userhome = os.environ['HOME']
342 elif not os.environ.has_key('HOMEPATH'):
343 return path
344 else:
345 try:
Fred Drakeb4e460a2000-09-28 16:25:20 +0000346 drive = os.environ['HOMEDRIVE']
Guido van Rossum15e22e11997-12-05 19:03:01 +0000347 except KeyError:
348 drive = ''
349 userhome = join(drive, os.environ['HOMEPATH'])
350 else:
351 return path
352 return userhome + path[i:]
Guido van Rossum555915a1994-02-24 11:32:59 +0000353
354
355# Expand paths containing shell variable substitutions.
356# The following rules apply:
Guido van Rossum15e22e11997-12-05 19:03:01 +0000357# - no expansion within single quotes
358# - no escape character, except for '$$' which is translated into '$'
359# - ${varname} is accepted.
360# - varnames can be made out of letters, digits and the character '_'
Guido van Rossum555915a1994-02-24 11:32:59 +0000361# XXX With COMMAND.COM you can use any characters in a variable name,
362# XXX except '^|<>='.
363
Tim Peters2344fae2001-01-15 00:50:52 +0000364def expandvars(path):
Guido van Rossum534972b1999-02-03 17:20:50 +0000365 """Expand shell variables of form $var and ${var}.
366
367 Unknown variables are left unchanged."""
Guido van Rossum15e22e11997-12-05 19:03:01 +0000368 if '$' not in path:
369 return path
Fred Drakeb4e460a2000-09-28 16:25:20 +0000370 import string
Fred Drake79e75e12001-07-20 19:05:50 +0000371 varchars = string.ascii_letters + string.digits + '_-'
Guido van Rossum15e22e11997-12-05 19:03:01 +0000372 res = ''
373 index = 0
374 pathlen = len(path)
375 while index < pathlen:
376 c = path[index]
377 if c == '\'': # no expansion within single quotes
378 path = path[index + 1:]
379 pathlen = len(path)
380 try:
Fred Drakeb4e460a2000-09-28 16:25:20 +0000381 index = path.index('\'')
Guido van Rossum15e22e11997-12-05 19:03:01 +0000382 res = res + '\'' + path[:index + 1]
Fred Drakeb4e460a2000-09-28 16:25:20 +0000383 except ValueError:
Guido van Rossum15e22e11997-12-05 19:03:01 +0000384 res = res + path
Fred Drakeb4e460a2000-09-28 16:25:20 +0000385 index = pathlen - 1
Guido van Rossum15e22e11997-12-05 19:03:01 +0000386 elif c == '$': # variable or '$$'
387 if path[index + 1:index + 2] == '$':
388 res = res + c
389 index = index + 1
390 elif path[index + 1:index + 2] == '{':
391 path = path[index+2:]
392 pathlen = len(path)
393 try:
Fred Drakeb4e460a2000-09-28 16:25:20 +0000394 index = path.index('}')
Guido van Rossum15e22e11997-12-05 19:03:01 +0000395 var = path[:index]
396 if os.environ.has_key(var):
397 res = res + os.environ[var]
Fred Drakeb4e460a2000-09-28 16:25:20 +0000398 except ValueError:
Guido van Rossum15e22e11997-12-05 19:03:01 +0000399 res = res + path
400 index = pathlen - 1
401 else:
402 var = ''
403 index = index + 1
404 c = path[index:index + 1]
405 while c != '' and c in varchars:
406 var = var + c
407 index = index + 1
408 c = path[index:index + 1]
409 if os.environ.has_key(var):
410 res = res + os.environ[var]
411 if c != '':
412 res = res + c
413 else:
414 res = res + c
415 index = index + 1
416 return res
Guido van Rossum555915a1994-02-24 11:32:59 +0000417
418
Tim Peters54a14a32001-08-30 22:05:26 +0000419# Normalize a path, e.g. A//B, A/./B and A/foo/../B all become A\B.
Guido van Rossum3df7b5a1996-08-26 16:35:26 +0000420# Previously, this function also truncated pathnames to 8+3 format,
421# but as this module is called "ntpath", that's obviously wrong!
Guido van Rossum555915a1994-02-24 11:32:59 +0000422
423def normpath(path):
Guido van Rossum15e22e11997-12-05 19:03:01 +0000424 """Normalize path, eliminating double slashes, etc."""
Fred Drakeb4e460a2000-09-28 16:25:20 +0000425 path = path.replace("/", "\\")
Guido van Rossum15e22e11997-12-05 19:03:01 +0000426 prefix, path = splitdrive(path)
Fred Drakeb4e460a2000-09-28 16:25:20 +0000427 while path[:1] == "\\":
428 prefix = prefix + "\\"
Guido van Rossum15e22e11997-12-05 19:03:01 +0000429 path = path[1:]
Fred Drakeb4e460a2000-09-28 16:25:20 +0000430 comps = path.split("\\")
Guido van Rossum15e22e11997-12-05 19:03:01 +0000431 i = 0
432 while i < len(comps):
Tim Peters54a14a32001-08-30 22:05:26 +0000433 if comps[i] in ('.', ''):
Guido van Rossum15e22e11997-12-05 19:03:01 +0000434 del comps[i]
Tim Peters54a14a32001-08-30 22:05:26 +0000435 elif comps[i] == '..':
436 if i > 0 and comps[i-1] != '..':
437 del comps[i-1:i+1]
438 i -= 1
439 elif i == 0 and prefix.endswith("\\"):
440 del comps[i]
441 else:
442 i += 1
Guido van Rossum15e22e11997-12-05 19:03:01 +0000443 else:
Tim Peters54a14a32001-08-30 22:05:26 +0000444 i += 1
Guido van Rossum15e22e11997-12-05 19:03:01 +0000445 # If the path is now empty, substitute '.'
446 if not prefix and not comps:
447 comps.append('.')
Fred Drakeb4e460a2000-09-28 16:25:20 +0000448 return prefix + "\\".join(comps)
Guido van Rossume294cf61999-01-29 18:05:18 +0000449
450
451# Return an absolute path.
452def abspath(path):
Guido van Rossum534972b1999-02-03 17:20:50 +0000453 """Return the absolute version of a path"""
Mark Hammond647d2fe2000-08-14 06:20:32 +0000454 if path: # Empty path must return current working directory.
Mark Hammondef8b6542001-05-13 08:04:26 +0000455 from nt import _getfullpathname
Mark Hammond647d2fe2000-08-14 06:20:32 +0000456 try:
Mark Hammondef8b6542001-05-13 08:04:26 +0000457 path = _getfullpathname(path)
458 except WindowsError:
Fred Drakeda05e972001-05-15 15:23:01 +0000459 pass # Bad path - return unchanged.
Mark Hammond647d2fe2000-08-14 06:20:32 +0000460 else:
461 path = os.getcwd()
Guido van Rossum6dfc7921999-11-30 15:00:00 +0000462 return normpath(path)
Guido van Rossum83eeef42001-09-17 15:16:09 +0000463
464# realpath is a no-op on systems without islink support
465realpath = abspath