Module posixpath
[hide private]
[frames] | no frames]

Source Code for Module posixpath

  1  """Common operations on Posix pathnames. 
  2   
  3  Instead of importing this module directly, import os and refer to 
  4  this module as os.path.  The "os.path" name is an alias for this 
  5  module on Posix systems; on other systems (e.g. Mac, Windows), 
  6  os.path provides the same operations in a manner specific to that 
  7  platform, and is an alias to another module (e.g. macpath, ntpath). 
  8   
  9  Some of this can actually be useful on non-Posix systems too, e.g. 
 10  for manipulation of the pathname component of URLs. 
 11  """ 
 12   
 13  import os 
 14  import stat 
 15   
 16  __all__ = ["normcase","isabs","join","splitdrive","split","splitext", 
 17             "basename","dirname","commonprefix","getsize","getmtime", 
 18             "getatime","getctime","islink","exists","lexists","isdir","isfile", 
 19             "ismount","walk","expanduser","expandvars","normpath","abspath", 
 20             "samefile","sameopenfile","samestat", 
 21             "curdir","pardir","sep","pathsep","defpath","altsep","extsep", 
 22             "devnull","realpath","supports_unicode_filenames"] 
 23   
 24  # strings representing various path-related bits and pieces 
 25  curdir = '.' 
 26  pardir = '..' 
 27  extsep = '.' 
 28  sep = '/' 
 29  pathsep = ':' 
 30  defpath = ':/bin:/usr/bin' 
 31  altsep = None 
 32  devnull = '/dev/null' 
 33   
 34  # Normalize the case of a pathname.  Trivial in Posix, string.lower on Mac. 
 35  # On MS-DOS this may also turn slashes into backslashes; however, other 
 36  # normalizations (such as optimizing '../' away) are not allowed 
 37  # (another function should be defined to do that). 
 38   
39 -def normcase(s):
40 """Normalize case of pathname. Has no effect under Posix""" 41 return s
42 43 44 # Return whether a path is absolute. 45 # Trivial in Posix, harder on the Mac or MS-DOS. 46
47 -def isabs(s):
48 """Test whether a path is absolute""" 49 return s.startswith('/')
50 51 52 # Join pathnames. 53 # Ignore the previous parts if a part is absolute. 54 # Insert a '/' unless the first part is empty or already ends in '/'. 55
56 -def join(a, *p):
57 """Join two or more pathname components, inserting '/' as needed""" 58 path = a 59 for b in p: 60 if b.startswith('/'): 61 path = b 62 elif path == '' or path.endswith('/'): 63 path += b 64 else: 65 path += '/' + b 66 return path
67 68 69 # Split a path in head (everything up to the last '/') and tail (the 70 # rest). If the path ends in '/', tail will be empty. If there is no 71 # '/' in the path, head will be empty. 72 # Trailing '/'es are stripped from head unless it is the root. 73
74 -def split(p):
75 """Split a pathname. Returns tuple "(head, tail)" where "tail" is 76 everything after the final slash. Either part may be empty.""" 77 i = p.rfind('/') + 1 78 head, tail = p[:i], p[i:] 79 if head and head != '/'*len(head): 80 head = head.rstrip('/') 81 return head, tail
82 83 84 # Split a path in root and extension. 85 # The extension is everything starting at the last dot in the last 86 # pathname component; the root is everything before that. 87 # It is always true that root + ext == p. 88
89 -def splitext(p):
90 """Split the extension from a pathname. Extension is everything from the 91 last dot to the end. Returns "(root, ext)", either part may be empty.""" 92 i = p.rfind('.') 93 if i<=p.rfind('/'): 94 return p, '' 95 else: 96 return p[:i], p[i:]
97 98 99 # Split a pathname into a drive specification and the rest of the 100 # path. Useful on DOS/Windows/NT; on Unix, the drive is always empty. 101
102 -def splitdrive(p):
103 """Split a pathname into drive and path. On Posix, drive is always 104 empty.""" 105 return '', p
106 107 108 # Return the tail (basename) part of a path. 109
110 -def basename(p):
111 """Returns the final component of a pathname""" 112 return split(p)[1]
113 114 115 # Return the head (dirname) part of a path. 116
117 -def dirname(p):
118 """Returns the directory component of a pathname""" 119 return split(p)[0]
120 121 122 # Return the longest prefix of all list elements. 123
124 -def commonprefix(m):
125 "Given a list of pathnames, returns the longest common leading component" 126 if not m: return '' 127 s1 = min(m) 128 s2 = max(m) 129 n = min(len(s1), len(s2)) 130 for i in xrange(n): 131 if s1[i] != s2[i]: 132 return s1[:i] 133 return s1[:n]
134 135 # Get size, mtime, atime of files. 136
137 -def getsize(filename):
138 """Return the size of a file, reported by os.stat().""" 139 return os.stat(filename).st_size
140
141 -def getmtime(filename):
142 """Return the last modification time of a file, reported by os.stat().""" 143 return os.stat(filename).st_mtime
144
145 -def getatime(filename):
146 """Return the last access time of a file, reported by os.stat().""" 147 return os.stat(filename).st_atime
148
149 -def getctime(filename):
150 """Return the metadata change time of a file, reported by os.stat().""" 151 return os.stat(filename).st_ctime
152 153 # Is a path a symbolic link? 154 # This will always return false on systems where os.lstat doesn't exist. 155 163 164 165 # Does a path exist? 166 # This is false for dangling symbolic links. 167
168 -def exists(path):
169 """Test whether a path exists. Returns False for broken symbolic links""" 170 try: 171 st = os.stat(path) 172 except os.error: 173 return False 174 return True
175 176 177 # Being true for dangling symbolic links is also useful. 178
179 -def lexists(path):
180 """Test whether a path exists. Returns True for broken symbolic links""" 181 try: 182 st = os.lstat(path) 183 except os.error: 184 return False 185 return True
186 187 188 # Is a path a directory? 189 # This follows symbolic links, so both islink() and isdir() can be true 190 # for the same path. 191
192 -def isdir(path):
193 """Test whether a path is a directory""" 194 try: 195 st = os.stat(path) 196 except os.error: 197 return False 198 return stat.S_ISDIR(st.st_mode)
199 200 201 # Is a path a regular file? 202 # This follows symbolic links, so both islink() and isfile() can be true 203 # for the same path. 204
205 -def isfile(path):
206 """Test whether a path is a regular file""" 207 try: 208 st = os.stat(path) 209 except os.error: 210 return False 211 return stat.S_ISREG(st.st_mode)
212 213 214 # Are two filenames really pointing to the same file? 215
216 -def samefile(f1, f2):
217 """Test whether two pathnames reference the same actual file""" 218 s1 = os.stat(f1) 219 s2 = os.stat(f2) 220 return samestat(s1, s2)
221 222 223 # Are two open files really referencing the same file? 224 # (Not necessarily the same file descriptor!) 225
226 -def sameopenfile(fp1, fp2):
227 """Test whether two open file objects reference the same file""" 228 s1 = os.fstat(fp1) 229 s2 = os.fstat(fp2) 230 return samestat(s1, s2)
231 232 233 # Are two stat buffers (obtained from stat, fstat or lstat) 234 # describing the same file? 235
236 -def samestat(s1, s2):
237 """Test whether two stat buffers reference the same file""" 238 return s1.st_ino == s2.st_ino and \ 239 s1.st_dev == s2.st_dev
240 241 242 # Is a path a mount point? 243 # (Does this work for all UNIXes? Is it even guaranteed to work by Posix?) 244
245 -def ismount(path):
246 """Test whether a path is a mount point""" 247 try: 248 s1 = os.lstat(path) 249 s2 = os.lstat(join(path, '..')) 250 except os.error: 251 return False # It doesn't exist -- so not a mount point :-) 252 dev1 = s1.st_dev 253 dev2 = s2.st_dev 254 if dev1 != dev2: 255 return True # path/.. on a different device as path 256 ino1 = s1.st_ino 257 ino2 = s2.st_ino 258 if ino1 == ino2: 259 return True # path/.. is the same i-node as path 260 return False
261 262 263 # Directory tree walk. 264 # For each directory under top (including top itself, but excluding 265 # '.' and '..'), func(arg, dirname, filenames) is called, where 266 # dirname is the name of the directory and filenames is the list 267 # of files (and subdirectories etc.) in the directory. 268 # The func may modify the filenames list, to implement a filter, 269 # or to impose a different order of visiting. 270
271 -def walk(top, func, arg):
272 """Directory tree walk with callback function. 273 274 For each directory in the directory tree rooted at top (including top 275 itself, but excluding '.' and '..'), call func(arg, dirname, fnames). 276 dirname is the name of the directory, and fnames a list of the names of 277 the files and subdirectories in dirname (excluding '.' and '..'). func 278 may modify the fnames list in-place (e.g. via del or slice assignment), 279 and walk will only recurse into the subdirectories whose names remain in 280 fnames; this can be used to implement a filter, or to impose a specific 281 order of visiting. No semantics are defined for, or required of, arg, 282 beyond that arg is always passed to func. It can be used, e.g., to pass 283 a filename pattern, or a mutable object designed to accumulate 284 statistics. Passing None for arg is common.""" 285 286 try: 287 names = os.listdir(top) 288 except os.error: 289 return 290 func(arg, top, names) 291 for name in names: 292 name = join(top, name) 293 try: 294 st = os.lstat(name) 295 except os.error: 296 continue 297 if stat.S_ISDIR(st.st_mode): 298 walk(name, func, arg)
299 300 301 # Expand paths beginning with '~' or '~user'. 302 # '~' means $HOME; '~user' means that user's home directory. 303 # If the path doesn't begin with '~', or if the user or $HOME is unknown, 304 # the path is returned unchanged (leaving error reporting to whatever 305 # function is called with the expanded path as argument). 306 # See also module 'glob' for expansion of *, ? and [...] in pathnames. 307 # (A function should also be defined to do full *sh-style environment 308 # variable expansion.) 309
310 -def expanduser(path):
311 """Expand ~ and ~user constructions. If user or $HOME is unknown, 312 do nothing.""" 313 if not path.startswith('~'): 314 return path 315 i = path.find('/', 1) 316 if i < 0: 317 i = len(path) 318 if i == 1: 319 if 'HOME' not in os.environ: 320 import pwd 321 userhome = pwd.getpwuid(os.getuid()).pw_dir 322 else: 323 userhome = os.environ['HOME'] 324 else: 325 import pwd 326 try: 327 pwent = pwd.getpwnam(path[1:i]) 328 except KeyError: 329 return path 330 userhome = pwent.pw_dir 331 userhome = userhome.rstrip('/') 332 return userhome + path[i:]
333 334 335 # Expand paths containing shell variable substitutions. 336 # This expands the forms $variable and ${variable} only. 337 # Non-existent variables are left unchanged. 338 339 _varprog = None 340
341 -def expandvars(path):
342 """Expand shell variables of form $var and ${var}. Unknown variables 343 are left unchanged.""" 344 global _varprog 345 if '$' not in path: 346 return path 347 if not _varprog: 348 import re 349 _varprog = re.compile(r'\$(\w+|\{[^}]*\})') 350 i = 0 351 while True: 352 m = _varprog.search(path, i) 353 if not m: 354 break 355 i, j = m.span(0) 356 name = m.group(1) 357 if name.startswith('{') and name.endswith('}'): 358 name = name[1:-1] 359 if name in os.environ: 360 tail = path[j:] 361 path = path[:i] + os.environ[name] 362 i = len(path) 363 path += tail 364 else: 365 i = j 366 return path
367 368 369 # Normalize a path, e.g. A//B, A/./B and A/foo/../B all become A/B. 370 # It should be understood that this may change the meaning of the path 371 # if it contains symbolic links! 372
373 -def normpath(path):
374 """Normalize path, eliminating double slashes, etc.""" 375 if path == '': 376 return '.' 377 initial_slashes = path.startswith('/') 378 # POSIX allows one or two initial slashes, but treats three or more 379 # as single slash. 380 if (initial_slashes and 381 path.startswith('//') and not path.startswith('///')): 382 initial_slashes = 2 383 comps = path.split('/') 384 new_comps = [] 385 for comp in comps: 386 if comp in ('', '.'): 387 continue 388 if (comp != '..' or (not initial_slashes and not new_comps) or 389 (new_comps and new_comps[-1] == '..')): 390 new_comps.append(comp) 391 elif new_comps: 392 new_comps.pop() 393 comps = new_comps 394 path = '/'.join(comps) 395 if initial_slashes: 396 path = '/'*initial_slashes + path 397 return path or '.'
398 399
400 -def abspath(path):
401 """Return an absolute path.""" 402 if not isabs(path): 403 path = join(os.getcwd(), path) 404 return normpath(path)
405 406 407 # Return a canonical path (i.e. the absolute location of a file on the 408 # filesystem). 409
410 -def realpath(filename):
411 """Return the canonical path of the specified filename, eliminating any 412 symbolic links encountered in the path.""" 413 if isabs(filename): 414 bits = ['/'] + filename.split('/')[1:] 415 else: 416 bits = [''] + filename.split('/') 417 418 for i in range(2, len(bits)+1): 419 component = join(*bits[0:i]) 420 # Resolve symbolic links. 421 if islink(component): 422 resolved = _resolve_link(component) 423 if resolved is None: 424 # Infinite loop -- return original component + rest of the path 425 return abspath(join(*([component] + bits[i:]))) 426 else: 427 newpath = join(*([resolved] + bits[i:])) 428 return realpath(newpath) 429 430 return abspath(filename)
431 432 452 453 supports_unicode_filenames = False 454