blob: b32ec164bb9d89c9b8072dbbe977632740ee4061 [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
Mark Hammond8696ebc2002-10-08 02:44:31 +000010import sys
Jack Diederich7b604642006-08-26 18:42:06 +000011from genericpath import *
Skip Montanaro4d5d5bf2000-07-13 01:01:03 +000012
Skip Montanaro269b83b2001-02-06 01:07:02 +000013__all__ = ["normcase","isabs","join","splitdrive","split","splitext",
14 "basename","dirname","commonprefix","getsize","getmtime",
Georg Brandlf0de6a12005-08-22 18:02:59 +000015 "getatime","getctime", "islink","exists","lexists","isdir","isfile",
16 "ismount","walk","expanduser","expandvars","normpath","abspath",
17 "splitunc","curdir","pardir","sep","pathsep","defpath","altsep",
18 "extsep","devnull","realpath","supports_unicode_filenames"]
Guido van Rossum555915a1994-02-24 11:32:59 +000019
Skip Montanaro117910d2003-02-14 19:35:31 +000020# strings representing various path-related bits and pieces
21curdir = '.'
22pardir = '..'
23extsep = '.'
24sep = '\\'
25pathsep = ';'
Skip Montanaro9ddac3e2003-03-28 22:23:24 +000026altsep = '/'
Andrew MacIntyre437966c2003-02-17 09:17:50 +000027defpath = '.;C:\\bin'
Skip Montanaro117910d2003-02-14 19:35:31 +000028if 'ce' in sys.builtin_module_names:
29 defpath = '\\Windows'
30elif 'os2' in sys.builtin_module_names:
Andrew MacIntyre437966c2003-02-17 09:17:50 +000031 # OS/2 w/ VACPP
Skip Montanaro117910d2003-02-14 19:35:31 +000032 altsep = '/'
Martin v. Löwisbdec50f2004-06-08 08:29:33 +000033devnull = 'nul'
Skip Montanaro117910d2003-02-14 19:35:31 +000034
Guido van Rossume2ad88c1997-08-12 14:46:58 +000035# Normalize the case of a pathname and map slashes to backslashes.
36# Other normalizations (such as optimizing '../' away) are not done
Guido van Rossum555915a1994-02-24 11:32:59 +000037# (this is done by normpath).
Guido van Rossume2ad88c1997-08-12 14:46:58 +000038
Guido van Rossum555915a1994-02-24 11:32:59 +000039def normcase(s):
Guido van Rossum16a0bc21998-02-18 13:48:31 +000040 """Normalize case of pathname.
41
Guido van Rossum534972b1999-02-03 17:20:50 +000042 Makes all characters lowercase and all slashes into backslashes."""
Fred Drakeb4e460a2000-09-28 16:25:20 +000043 return s.replace("/", "\\").lower()
Guido van Rossum555915a1994-02-24 11:32:59 +000044
Guido van Rossum77e1db31997-06-02 23:11:57 +000045
Fred Drakeef0b5dd2000-02-17 17:30:40 +000046# Return whether a path is absolute.
Guido van Rossum555915a1994-02-24 11:32:59 +000047# Trivial in Posix, harder on the Mac or MS-DOS.
48# For DOS it is absolute if it starts with a slash or backslash (current
Guido van Rossum534972b1999-02-03 17:20:50 +000049# volume), or if a pathname after the volume letter and colon / UNC resource
50# starts with a slash or backslash.
Guido van Rossum555915a1994-02-24 11:32:59 +000051
52def isabs(s):
Guido van Rossum15e22e11997-12-05 19:03:01 +000053 """Test whether a path is absolute"""
54 s = splitdrive(s)[1]
55 return s != '' and s[:1] in '/\\'
Guido van Rossum555915a1994-02-24 11:32:59 +000056
57
Guido van Rossum77e1db31997-06-02 23:11:57 +000058# Join two (or more) paths.
59
Barry Warsaw384d2491997-02-18 21:53:25 +000060def join(a, *p):
Guido van Rossum15e22e11997-12-05 19:03:01 +000061 """Join two or more pathname components, inserting "\\" as needed"""
62 path = a
63 for b in p:
Tim Peters33dc0a12001-07-27 08:09:54 +000064 b_wins = 0 # set to 1 iff b makes path irrelevant
65 if path == "":
66 b_wins = 1
Tim Peters1bdd0f22001-07-19 17:18:18 +000067
Tim Peters33dc0a12001-07-27 08:09:54 +000068 elif isabs(b):
69 # This probably wipes out path so far. However, it's more
70 # complicated if path begins with a drive letter:
71 # 1. join('c:', '/a') == 'c:/a'
72 # 2. join('c:/', '/a') == 'c:/a'
73 # But
74 # 3. join('c:/a', '/b') == '/b'
75 # 4. join('c:', 'd:/') = 'd:/'
76 # 5. join('c:/', 'd:/') = 'd:/'
77 if path[1:2] != ":" or b[1:2] == ":":
78 # Path doesn't start with a drive letter, or cases 4 and 5.
79 b_wins = 1
Tim Peters1bdd0f22001-07-19 17:18:18 +000080
Tim Peters33dc0a12001-07-27 08:09:54 +000081 # Else path has a drive letter, and b doesn't but is absolute.
82 elif len(path) > 3 or (len(path) == 3 and
83 path[-1] not in "/\\"):
84 # case 3
85 b_wins = 1
Tim Peters1bdd0f22001-07-19 17:18:18 +000086
Tim Peters33dc0a12001-07-27 08:09:54 +000087 if b_wins:
88 path = b
89 else:
90 # Join, and ensure there's a separator.
91 assert len(path) > 0
92 if path[-1] in "/\\":
93 if b and b[0] in "/\\":
94 path += b[1:]
95 else:
96 path += b
97 elif path[-1] == ":":
98 path += b
99 elif b:
100 if b[0] in "/\\":
101 path += b
102 else:
103 path += "\\" + b
Tim Peters6a3e5f12001-11-05 21:25:02 +0000104 else:
105 # path is not empty and does not end with a backslash,
106 # but b is empty; since, e.g., split('a/') produces
107 # ('a', ''), it's best if join() adds a backslash in
108 # this case.
109 path += '\\'
Tim Peters1bdd0f22001-07-19 17:18:18 +0000110
Guido van Rossum15e22e11997-12-05 19:03:01 +0000111 return path
Guido van Rossum555915a1994-02-24 11:32:59 +0000112
113
114# Split a path in a drive specification (a drive letter followed by a
Guido van Rossumf3c695c1999-04-06 19:32:19 +0000115# colon) and the path specification.
Guido van Rossum555915a1994-02-24 11:32:59 +0000116# It is always true that drivespec + pathspec == p
117def splitdrive(p):
Guido van Rossumf3c695c1999-04-06 19:32:19 +0000118 """Split a pathname into drive and path specifiers. Returns a 2-tuple
119"(drive,path)"; either part may be empty"""
Guido van Rossum15e22e11997-12-05 19:03:01 +0000120 if p[1:2] == ':':
121 return p[0:2], p[2:]
Guido van Rossumf3c695c1999-04-06 19:32:19 +0000122 return '', p
123
124
125# Parse UNC paths
126def splitunc(p):
127 """Split a pathname into UNC mount point and relative path specifiers.
128
129 Return a 2-tuple (unc, rest); either part may be empty.
130 If unc is not empty, it has the form '//host/mount' (or similar
131 using backslashes). unc+rest is always the input path.
132 Paths containing drive letters never have an UNC part.
133 """
134 if p[1:2] == ':':
135 return '', p # Drive letter present
Guido van Rossum534972b1999-02-03 17:20:50 +0000136 firstTwo = p[0:2]
137 if firstTwo == '//' or firstTwo == '\\\\':
138 # is a UNC path:
139 # vvvvvvvvvvvvvvvvvvvv equivalent to drive letter
140 # \\machine\mountpoint\directories...
141 # directory ^^^^^^^^^^^^^^^
142 normp = normcase(p)
Fred Drakeb4e460a2000-09-28 16:25:20 +0000143 index = normp.find('\\', 2)
Guido van Rossum534972b1999-02-03 17:20:50 +0000144 if index == -1:
145 ##raise RuntimeError, 'illegal UNC path: "' + p + '"'
146 return ("", p)
Fred Drakeb4e460a2000-09-28 16:25:20 +0000147 index = normp.find('\\', index + 1)
Guido van Rossum534972b1999-02-03 17:20:50 +0000148 if index == -1:
149 index = len(p)
150 return p[:index], p[index:]
Guido van Rossum15e22e11997-12-05 19:03:01 +0000151 return '', p
Guido van Rossum555915a1994-02-24 11:32:59 +0000152
153
154# Split a path in head (everything up to the last '/') and tail (the
Guido van Rossum8f0fa9e1999-03-19 21:05:12 +0000155# rest). After the trailing '/' is stripped, the invariant
Guido van Rossum555915a1994-02-24 11:32:59 +0000156# join(head, tail) == p holds.
157# The resulting head won't end in '/' unless it is the root.
158
159def split(p):
Guido van Rossum534972b1999-02-03 17:20:50 +0000160 """Split a pathname.
161
162 Return tuple (head, tail) where tail is everything after the final slash.
163 Either part may be empty."""
Guido van Rossum8f0fa9e1999-03-19 21:05:12 +0000164
Guido van Rossum15e22e11997-12-05 19:03:01 +0000165 d, p = splitdrive(p)
Guido van Rossum8f0fa9e1999-03-19 21:05:12 +0000166 # set i to index beyond p's last slash
167 i = len(p)
168 while i and p[i-1] not in '/\\':
169 i = i - 1
170 head, tail = p[:i], p[i:] # now tail has no slashes
171 # remove trailing slashes from head, unless it's all slashes
172 head2 = head
173 while head2 and head2[-1] in '/\\':
174 head2 = head2[:-1]
175 head = head2 or head
Guido van Rossum15e22e11997-12-05 19:03:01 +0000176 return d + head, tail
Guido van Rossum555915a1994-02-24 11:32:59 +0000177
178
179# Split a path in root and extension.
Guido van Rossum73e122f1997-01-22 00:17:26 +0000180# The extension is everything starting at the last dot in the last
Guido van Rossum555915a1994-02-24 11:32:59 +0000181# pathname component; the root is everything before that.
182# It is always true that root + ext == p.
183
184def splitext(p):
Guido van Rossum534972b1999-02-03 17:20:50 +0000185 """Split the extension from a pathname.
186
187 Extension is everything from the last dot to the end.
188 Return (root, ext), either part may be empty."""
Martin v. Löwisde333792002-12-12 20:30:20 +0000189
190 i = p.rfind('.')
191 if i<=max(p.rfind('/'), p.rfind('\\')):
192 return p, ''
193 else:
194 return p[:i], p[i:]
Guido van Rossum555915a1994-02-24 11:32:59 +0000195
196
197# Return the tail (basename) part of a path.
198
199def basename(p):
Guido van Rossum15e22e11997-12-05 19:03:01 +0000200 """Returns the final component of a pathname"""
201 return split(p)[1]
Guido van Rossum555915a1994-02-24 11:32:59 +0000202
203
204# Return the head (dirname) part of a path.
205
206def dirname(p):
Guido van Rossum15e22e11997-12-05 19:03:01 +0000207 """Returns the directory component of a pathname"""
208 return split(p)[0]
Guido van Rossum555915a1994-02-24 11:32:59 +0000209
Guido van Rossum555915a1994-02-24 11:32:59 +0000210# Is a path a symbolic link?
211# This will always return false on systems where posix.lstat doesn't exist.
212
213def islink(path):
Jack Diederich7b604642006-08-26 18:42:06 +0000214 """Test for symbolic link.
215 On WindowsNT/95 and OS/2 always returns false
216 """
Guido van Rossum8ca162f2002-04-07 06:36:23 +0000217 return False
Guido van Rossum555915a1994-02-24 11:32:59 +0000218
Jack Diederich7b604642006-08-26 18:42:06 +0000219# alias exists to lexists
Johannes Gijsbersae882f72004-08-30 10:19:56 +0000220lexists = exists
221
Guido van Rossumf3c695c1999-04-06 19:32:19 +0000222# Is a path a mount point? Either a root (with or without drive letter)
223# or an UNC path with at most a / or \ after the mount point.
Guido van Rossum555915a1994-02-24 11:32:59 +0000224
225def ismount(path):
Guido van Rossumca99c2c1998-01-19 22:25:59 +0000226 """Test whether a path is a mount point (defined as root of drive)"""
Guido van Rossumf3c695c1999-04-06 19:32:19 +0000227 unc, rest = splitunc(path)
228 if unc:
229 return rest in ("", "/", "\\")
Guido van Rossumca99c2c1998-01-19 22:25:59 +0000230 p = splitdrive(path)[1]
Fred Drakeb4e460a2000-09-28 16:25:20 +0000231 return len(p) == 1 and p[0] in '/\\'
Guido van Rossum555915a1994-02-24 11:32:59 +0000232
233
234# Directory tree walk.
235# For each directory under top (including top itself, but excluding
236# '.' and '..'), func(arg, dirname, filenames) is called, where
237# dirname is the name of the directory and filenames is the list
Walter Dörwaldf0dfc7a2003-10-20 14:01:56 +0000238# of files (and subdirectories etc.) in the directory.
Guido van Rossum555915a1994-02-24 11:32:59 +0000239# The func may modify the filenames list, to implement a filter,
240# or to impose a different order of visiting.
241
242def walk(top, func, arg):
Tim Peterscf5e6a42001-10-10 04:16:20 +0000243 """Directory tree walk with callback function.
Guido van Rossum534972b1999-02-03 17:20:50 +0000244
Tim Peterscf5e6a42001-10-10 04:16:20 +0000245 For each directory in the directory tree rooted at top (including top
246 itself, but excluding '.' and '..'), call func(arg, dirname, fnames).
247 dirname is the name of the directory, and fnames a list of the names of
248 the files and subdirectories in dirname (excluding '.' and '..'). func
249 may modify the fnames list in-place (e.g. via del or slice assignment),
250 and walk will only recurse into the subdirectories whose names remain in
251 fnames; this can be used to implement a filter, or to impose a specific
252 order of visiting. No semantics are defined for, or required of, arg,
253 beyond that arg is always passed to func. It can be used, e.g., to pass
254 a filename pattern, or a mutable object designed to accumulate
255 statistics. Passing None for arg is common."""
256
Guido van Rossum15e22e11997-12-05 19:03:01 +0000257 try:
258 names = os.listdir(top)
259 except os.error:
260 return
261 func(arg, top, names)
262 exceptions = ('.', '..')
263 for name in names:
264 if name not in exceptions:
265 name = join(top, name)
266 if isdir(name):
267 walk(name, func, arg)
Guido van Rossum555915a1994-02-24 11:32:59 +0000268
269
270# Expand paths beginning with '~' or '~user'.
271# '~' means $HOME; '~user' means that user's home directory.
272# If the path doesn't begin with '~', or if the user or $HOME is unknown,
273# the path is returned unchanged (leaving error reporting to whatever
274# function is called with the expanded path as argument).
275# See also module 'glob' for expansion of *, ? and [...] in pathnames.
276# (A function should also be defined to do full *sh-style environment
277# variable expansion.)
278
279def expanduser(path):
Guido van Rossum534972b1999-02-03 17:20:50 +0000280 """Expand ~ and ~user constructs.
281
282 If user or $HOME is unknown, do nothing."""
Fred Drake8152d322000-12-12 23:20:45 +0000283 if path[:1] != '~':
Guido van Rossum15e22e11997-12-05 19:03:01 +0000284 return path
285 i, n = 1, len(path)
286 while i < n and path[i] not in '/\\':
Fred Drakeb4e460a2000-09-28 16:25:20 +0000287 i = i + 1
Guido van Rossum15e22e11997-12-05 19:03:01 +0000288 if i == 1:
Raymond Hettinger54f02222002-06-01 14:18:47 +0000289 if 'HOME' in os.environ:
Guido van Rossum15e22e11997-12-05 19:03:01 +0000290 userhome = os.environ['HOME']
Raymond Hettinger54f02222002-06-01 14:18:47 +0000291 elif not 'HOMEPATH' in os.environ:
Guido van Rossum15e22e11997-12-05 19:03:01 +0000292 return path
293 else:
294 try:
Fred Drakeb4e460a2000-09-28 16:25:20 +0000295 drive = os.environ['HOMEDRIVE']
Guido van Rossum15e22e11997-12-05 19:03:01 +0000296 except KeyError:
297 drive = ''
298 userhome = join(drive, os.environ['HOMEPATH'])
299 else:
300 return path
301 return userhome + path[i:]
Guido van Rossum555915a1994-02-24 11:32:59 +0000302
303
304# Expand paths containing shell variable substitutions.
305# The following rules apply:
Guido van Rossum15e22e11997-12-05 19:03:01 +0000306# - no expansion within single quotes
307# - no escape character, except for '$$' which is translated into '$'
308# - ${varname} is accepted.
309# - varnames can be made out of letters, digits and the character '_'
Guido van Rossum555915a1994-02-24 11:32:59 +0000310# XXX With COMMAND.COM you can use any characters in a variable name,
311# XXX except '^|<>='.
312
Tim Peters2344fae2001-01-15 00:50:52 +0000313def expandvars(path):
Guido van Rossum534972b1999-02-03 17:20:50 +0000314 """Expand shell variables of form $var and ${var}.
315
316 Unknown variables are left unchanged."""
Guido van Rossum15e22e11997-12-05 19:03:01 +0000317 if '$' not in path:
318 return path
Fred Drakeb4e460a2000-09-28 16:25:20 +0000319 import string
Fred Drake79e75e12001-07-20 19:05:50 +0000320 varchars = string.ascii_letters + string.digits + '_-'
Guido van Rossum15e22e11997-12-05 19:03:01 +0000321 res = ''
322 index = 0
323 pathlen = len(path)
324 while index < pathlen:
325 c = path[index]
326 if c == '\'': # no expansion within single quotes
327 path = path[index + 1:]
328 pathlen = len(path)
329 try:
Fred Drakeb4e460a2000-09-28 16:25:20 +0000330 index = path.index('\'')
Guido van Rossum15e22e11997-12-05 19:03:01 +0000331 res = res + '\'' + path[:index + 1]
Fred Drakeb4e460a2000-09-28 16:25:20 +0000332 except ValueError:
Guido van Rossum15e22e11997-12-05 19:03:01 +0000333 res = res + path
Fred Drakeb4e460a2000-09-28 16:25:20 +0000334 index = pathlen - 1
Guido van Rossum15e22e11997-12-05 19:03:01 +0000335 elif c == '$': # variable or '$$'
336 if path[index + 1:index + 2] == '$':
337 res = res + c
338 index = index + 1
339 elif path[index + 1:index + 2] == '{':
340 path = path[index+2:]
341 pathlen = len(path)
342 try:
Fred Drakeb4e460a2000-09-28 16:25:20 +0000343 index = path.index('}')
Guido van Rossum15e22e11997-12-05 19:03:01 +0000344 var = path[:index]
Raymond Hettinger54f02222002-06-01 14:18:47 +0000345 if var in os.environ:
Guido van Rossum15e22e11997-12-05 19:03:01 +0000346 res = res + os.environ[var]
Fred Drakeb4e460a2000-09-28 16:25:20 +0000347 except ValueError:
Guido van Rossum15e22e11997-12-05 19:03:01 +0000348 res = res + path
349 index = pathlen - 1
350 else:
351 var = ''
352 index = index + 1
353 c = path[index:index + 1]
354 while c != '' and c in varchars:
355 var = var + c
356 index = index + 1
357 c = path[index:index + 1]
Raymond Hettinger54f02222002-06-01 14:18:47 +0000358 if var in os.environ:
Guido van Rossum15e22e11997-12-05 19:03:01 +0000359 res = res + os.environ[var]
360 if c != '':
361 res = res + c
362 else:
363 res = res + c
364 index = index + 1
365 return res
Guido van Rossum555915a1994-02-24 11:32:59 +0000366
367
Tim Peters54a14a32001-08-30 22:05:26 +0000368# 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 +0000369# Previously, this function also truncated pathnames to 8+3 format,
370# but as this module is called "ntpath", that's obviously wrong!
Guido van Rossum555915a1994-02-24 11:32:59 +0000371
372def normpath(path):
Guido van Rossum15e22e11997-12-05 19:03:01 +0000373 """Normalize path, eliminating double slashes, etc."""
Fred Drakeb4e460a2000-09-28 16:25:20 +0000374 path = path.replace("/", "\\")
Guido van Rossum15e22e11997-12-05 19:03:01 +0000375 prefix, path = splitdrive(path)
Brett Cannonbdc36272004-07-10 20:42:22 +0000376 # We need to be careful here. If the prefix is empty, and the path starts
377 # with a backslash, it could either be an absolute path on the current
378 # drive (\dir1\dir2\file) or a UNC filename (\\server\mount\dir1\file). It
379 # is therefore imperative NOT to collapse multiple backslashes blindly in
380 # that case.
381 # The code below preserves multiple backslashes when there is no drive
382 # letter. This means that the invalid filename \\\a\b is preserved
383 # unchanged, where a\\\b is normalised to a\b. It's not clear that there
384 # is any better behaviour for such edge cases.
385 if prefix == '':
386 # No drive letter - preserve initial backslashes
387 while path[:1] == "\\":
388 prefix = prefix + "\\"
389 path = path[1:]
390 else:
391 # We have a drive letter - collapse initial backslashes
392 if path.startswith("\\"):
393 prefix = prefix + "\\"
394 path = path.lstrip("\\")
Fred Drakeb4e460a2000-09-28 16:25:20 +0000395 comps = path.split("\\")
Guido van Rossum15e22e11997-12-05 19:03:01 +0000396 i = 0
397 while i < len(comps):
Tim Peters54a14a32001-08-30 22:05:26 +0000398 if comps[i] in ('.', ''):
Guido van Rossum15e22e11997-12-05 19:03:01 +0000399 del comps[i]
Tim Peters54a14a32001-08-30 22:05:26 +0000400 elif comps[i] == '..':
401 if i > 0 and comps[i-1] != '..':
402 del comps[i-1:i+1]
403 i -= 1
404 elif i == 0 and prefix.endswith("\\"):
405 del comps[i]
406 else:
407 i += 1
Guido van Rossum15e22e11997-12-05 19:03:01 +0000408 else:
Tim Peters54a14a32001-08-30 22:05:26 +0000409 i += 1
Guido van Rossum15e22e11997-12-05 19:03:01 +0000410 # If the path is now empty, substitute '.'
411 if not prefix and not comps:
412 comps.append('.')
Fred Drakeb4e460a2000-09-28 16:25:20 +0000413 return prefix + "\\".join(comps)
Guido van Rossume294cf61999-01-29 18:05:18 +0000414
415
416# Return an absolute path.
Tim Peters21fbd572006-04-21 21:18:10 +0000417try:
418 from nt import _getfullpathname
Mark Hammondf717f052002-01-17 00:44:26 +0000419
Tim Peters21fbd572006-04-21 21:18:10 +0000420except ImportError: # not running on Windows - mock up something sensible
421 def abspath(path):
422 """Return the absolute version of a path."""
423 if not isabs(path):
424 path = join(os.getcwd(), path)
425 return normpath(path)
426
427else: # use native Windows method on Windows
428 def abspath(path):
429 """Return the absolute version of a path."""
430
431 if path: # Empty path must return current working directory.
432 try:
433 path = _getfullpathname(path)
434 except WindowsError:
435 pass # Bad path - return unchanged.
436 else:
437 path = os.getcwd()
438 return normpath(path)
Guido van Rossum83eeef42001-09-17 15:16:09 +0000439
440# realpath is a no-op on systems without islink support
441realpath = abspath
Mark Hammond8696ebc2002-10-08 02:44:31 +0000442# Win9x family and earlier have no Unicode filename support.
Tim Peters26bc25a2002-10-09 07:56:04 +0000443supports_unicode_filenames = (hasattr(sys, "getwindowsversion") and
444 sys.getwindowsversion()[3] >= 2)