14710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm"""Common operations on Posix pathnames. 24710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 34710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmInstead of importing this module directly, import os and refer to 44710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmthis module as os.path. The "os.path" name is an alias for this 54710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmmodule on Posix systems; on other systems (e.g. Mac, Windows), 64710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmos.path provides the same operations in a manner specific to that 74710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmplatform, and is an alias to another module (e.g. macpath, ntpath). 84710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 94710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmSome of this can actually be useful on non-Posix systems too, e.g. 104710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmfor manipulation of the pathname component of URLs. 114710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm""" 124710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 134710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmimport os 144710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmimport sys 154710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmimport stat 164710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmimport genericpath 174710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmimport warnings 184710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmfrom genericpath import * 194710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 204710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm__all__ = ["normcase","isabs","join","splitdrive","split","splitext", 214710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm "basename","dirname","commonprefix","getsize","getmtime", 224710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm "getatime","getctime","islink","exists","lexists","isdir","isfile", 234710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm "ismount","walk","expanduser","expandvars","normpath","abspath", 244710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm "samefile","sameopenfile","samestat", 254710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm "curdir","pardir","sep","pathsep","defpath","altsep","extsep", 264710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm "devnull","realpath","supports_unicode_filenames","relpath"] 274710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 284710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# strings representing various path-related bits and pieces 294710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmcurdir = '.' 304710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmpardir = '..' 314710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmextsep = '.' 324710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmsep = '/' 334710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmpathsep = ':' 344710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmdefpath = ':/bin:/usr/bin' 354710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmaltsep = None 364710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmdevnull = '/dev/null' 374710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 384710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# Normalize the case of a pathname. Trivial in Posix, string.lower on Mac. 394710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# On MS-DOS this may also turn slashes into backslashes; however, other 404710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# normalizations (such as optimizing '../' away) are not allowed 414710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# (another function should be defined to do that). 424710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 434710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmdef normcase(s): 444710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm """Normalize case of pathname. Has no effect under Posix""" 454710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return s 464710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 474710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 484710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# Return whether a path is absolute. 494710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# Trivial in Posix, harder on the Mac or MS-DOS. 504710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 514710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmdef isabs(s): 524710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm """Test whether a path is absolute""" 534710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return s.startswith('/') 544710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 554710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 564710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# Join pathnames. 574710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# Ignore the previous parts if a part is absolute. 584710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# Insert a '/' unless the first part is empty or already ends in '/'. 594710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 604710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmdef join(a, *p): 614710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm """Join two or more pathname components, inserting '/' as needed. 624710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm If any component is an absolute path, all previous path components 634710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm will be discarded.""" 644710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm path = a 654710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm for b in p: 664710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if b.startswith('/'): 674710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm path = b 684710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm elif path == '' or path.endswith('/'): 694710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm path += b 704710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm else: 714710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm path += '/' + b 724710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return path 734710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 744710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 754710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# Split a path in head (everything up to the last '/') and tail (the 764710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# rest). If the path ends in '/', tail will be empty. If there is no 774710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# '/' in the path, head will be empty. 784710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# Trailing '/'es are stripped from head unless it is the root. 794710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 804710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmdef split(p): 814710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm """Split a pathname. Returns tuple "(head, tail)" where "tail" is 824710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm everything after the final slash. Either part may be empty.""" 834710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm i = p.rfind('/') + 1 844710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm head, tail = p[:i], p[i:] 854710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if head and head != '/'*len(head): 864710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm head = head.rstrip('/') 874710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return head, tail 884710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 894710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 904710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# Split a path in root and extension. 914710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# The extension is everything starting at the last dot in the last 924710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# pathname component; the root is everything before that. 934710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# It is always true that root + ext == p. 944710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 954710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmdef splitext(p): 964710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return genericpath._splitext(p, sep, altsep, extsep) 974710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmsplitext.__doc__ = genericpath._splitext.__doc__ 984710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 994710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# Split a pathname into a drive specification and the rest of the 1004710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# path. Useful on DOS/Windows/NT; on Unix, the drive is always empty. 1014710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 1024710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmdef splitdrive(p): 1034710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm """Split a pathname into drive and path. On Posix, drive is always 1044710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm empty.""" 1054710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return '', p 1064710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 1074710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 1084710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# Return the tail (basename) part of a path, same as split(path)[1]. 1094710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 1104710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmdef basename(p): 1114710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm """Returns the final component of a pathname""" 1124710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm i = p.rfind('/') + 1 1134710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return p[i:] 1144710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 1154710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 1164710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# Return the head (dirname) part of a path, same as split(path)[0]. 1174710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 1184710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmdef dirname(p): 1194710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm """Returns the directory component of a pathname""" 1204710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm i = p.rfind('/') + 1 1214710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm head = p[:i] 1224710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if head and head != '/'*len(head): 1234710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm head = head.rstrip('/') 1244710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return head 1254710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 1264710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 1274710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# Is a path a symbolic link? 1284710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# This will always return false on systems where os.lstat doesn't exist. 1294710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 1304710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmdef islink(path): 1314710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm """Test whether a path is a symbolic link""" 1324710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm try: 1334710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm st = os.lstat(path) 1344710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm except (os.error, AttributeError): 1354710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return False 1364710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return stat.S_ISLNK(st.st_mode) 1374710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 1384710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# Being true for dangling symbolic links is also useful. 1394710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 1404710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmdef lexists(path): 1414710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm """Test whether a path exists. Returns True for broken symbolic links""" 1424710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm try: 1434710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm os.lstat(path) 1444710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm except os.error: 1454710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return False 1464710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return True 1474710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 1484710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 1494710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# Are two filenames really pointing to the same file? 1504710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 1514710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmdef samefile(f1, f2): 1524710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm """Test whether two pathnames reference the same actual file""" 1534710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm s1 = os.stat(f1) 1544710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm s2 = os.stat(f2) 1554710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return samestat(s1, s2) 1564710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 1574710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 1584710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# Are two open files really referencing the same file? 1594710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# (Not necessarily the same file descriptor!) 1604710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 1614710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmdef sameopenfile(fp1, fp2): 1624710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm """Test whether two open file objects reference the same file""" 1634710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm s1 = os.fstat(fp1) 1644710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm s2 = os.fstat(fp2) 1654710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return samestat(s1, s2) 1664710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 1674710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 1684710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# Are two stat buffers (obtained from stat, fstat or lstat) 1694710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# describing the same file? 1704710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 1714710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmdef samestat(s1, s2): 1724710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm """Test whether two stat buffers reference the same file""" 1734710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return s1.st_ino == s2.st_ino and \ 1744710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm s1.st_dev == s2.st_dev 1754710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 1764710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 1774710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# Is a path a mount point? 1784710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# (Does this work for all UNIXes? Is it even guaranteed to work by Posix?) 1794710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 1804710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmdef ismount(path): 1814710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm """Test whether a path is a mount point""" 1824710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if islink(path): 1834710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # A symlink can never be a mount point 1844710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return False 1854710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm try: 1864710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm s1 = os.lstat(path) 1874710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm s2 = os.lstat(join(path, '..')) 1884710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm except os.error: 1894710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return False # It doesn't exist -- so not a mount point :-) 1904710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm dev1 = s1.st_dev 1914710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm dev2 = s2.st_dev 1924710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if dev1 != dev2: 1934710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return True # path/.. on a different device as path 1944710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm ino1 = s1.st_ino 1954710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm ino2 = s2.st_ino 1964710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if ino1 == ino2: 1974710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return True # path/.. is the same i-node as path 1984710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return False 1994710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 2004710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 2014710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# Directory tree walk. 2024710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# For each directory under top (including top itself, but excluding 2034710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# '.' and '..'), func(arg, dirname, filenames) is called, where 2044710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# dirname is the name of the directory and filenames is the list 2054710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# of files (and subdirectories etc.) in the directory. 2064710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# The func may modify the filenames list, to implement a filter, 2074710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# or to impose a different order of visiting. 2084710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 2094710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmdef walk(top, func, arg): 2104710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm """Directory tree walk with callback function. 2114710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 2124710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm For each directory in the directory tree rooted at top (including top 2134710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm itself, but excluding '.' and '..'), call func(arg, dirname, fnames). 2144710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm dirname is the name of the directory, and fnames a list of the names of 2154710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm the files and subdirectories in dirname (excluding '.' and '..'). func 2164710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm may modify the fnames list in-place (e.g. via del or slice assignment), 2174710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm and walk will only recurse into the subdirectories whose names remain in 2184710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm fnames; this can be used to implement a filter, or to impose a specific 2194710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm order of visiting. No semantics are defined for, or required of, arg, 2204710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm beyond that arg is always passed to func. It can be used, e.g., to pass 2214710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm a filename pattern, or a mutable object designed to accumulate 2224710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm statistics. Passing None for arg is common.""" 2234710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm warnings.warnpy3k("In 3.x, os.path.walk is removed in favor of os.walk.", 2244710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm stacklevel=2) 2254710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm try: 2264710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm names = os.listdir(top) 2274710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm except os.error: 2284710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return 2294710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm func(arg, top, names) 2304710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm for name in names: 2314710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm name = join(top, name) 2324710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm try: 2334710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm st = os.lstat(name) 2344710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm except os.error: 2354710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm continue 2364710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if stat.S_ISDIR(st.st_mode): 2374710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm walk(name, func, arg) 2384710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 2394710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 2404710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# Expand paths beginning with '~' or '~user'. 2414710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# '~' means $HOME; '~user' means that user's home directory. 2424710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# If the path doesn't begin with '~', or if the user or $HOME is unknown, 2434710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# the path is returned unchanged (leaving error reporting to whatever 2444710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# function is called with the expanded path as argument). 2454710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# See also module 'glob' for expansion of *, ? and [...] in pathnames. 2464710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# (A function should also be defined to do full *sh-style environment 2474710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# variable expansion.) 2484710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 2494710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmdef expanduser(path): 2504710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm """Expand ~ and ~user constructions. If user or $HOME is unknown, 2514710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm do nothing.""" 2524710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if not path.startswith('~'): 2534710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return path 2544710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm i = path.find('/', 1) 2554710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if i < 0: 2564710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm i = len(path) 2574710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if i == 1: 2584710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if 'HOME' not in os.environ: 2594710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm import pwd 2604710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm userhome = pwd.getpwuid(os.getuid()).pw_dir 2614710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm else: 2624710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm userhome = os.environ['HOME'] 2634710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm else: 2644710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm import pwd 2654710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm try: 2664710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm pwent = pwd.getpwnam(path[1:i]) 2674710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm except KeyError: 2684710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return path 2694710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm userhome = pwent.pw_dir 2704710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm userhome = userhome.rstrip('/') or userhome 2714710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return userhome + path[i:] 2724710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 2734710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 2744710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# Expand paths containing shell variable substitutions. 2754710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# This expands the forms $variable and ${variable} only. 2764710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# Non-existent variables are left unchanged. 2774710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 2784710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm_varprog = None 2794710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 2804710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmdef expandvars(path): 2814710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm """Expand shell variables of form $var and ${var}. Unknown variables 2824710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm are left unchanged.""" 2834710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm global _varprog 2844710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if '$' not in path: 2854710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return path 2864710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if not _varprog: 2874710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm import re 2884710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm _varprog = re.compile(r'\$(\w+|\{[^}]*\})') 2894710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm i = 0 2904710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm while True: 2914710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm m = _varprog.search(path, i) 2924710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if not m: 2934710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm break 2944710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm i, j = m.span(0) 2954710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm name = m.group(1) 2964710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if name.startswith('{') and name.endswith('}'): 2974710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm name = name[1:-1] 2984710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if name in os.environ: 2994710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm tail = path[j:] 3004710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm path = path[:i] + os.environ[name] 3014710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm i = len(path) 3024710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm path += tail 3034710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm else: 3044710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm i = j 3054710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return path 3064710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 3074710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 3084710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# Normalize a path, e.g. A//B, A/./B and A/foo/../B all become A/B. 3094710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# It should be understood that this may change the meaning of the path 3104710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# if it contains symbolic links! 3114710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 3124710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmdef normpath(path): 3134710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm """Normalize path, eliminating double slashes, etc.""" 3144710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # Preserve unicode (if path is unicode) 3154710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm slash, dot = (u'/', u'.') if isinstance(path, unicode) else ('/', '.') 3164710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if path == '': 3174710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return dot 3184710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm initial_slashes = path.startswith('/') 3194710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # POSIX allows one or two initial slashes, but treats three or more 3204710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # as single slash. 3214710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if (initial_slashes and 3224710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm path.startswith('//') and not path.startswith('///')): 3234710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm initial_slashes = 2 3244710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm comps = path.split('/') 3254710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm new_comps = [] 3264710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm for comp in comps: 3274710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if comp in ('', '.'): 3284710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm continue 3294710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if (comp != '..' or (not initial_slashes and not new_comps) or 3304710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm (new_comps and new_comps[-1] == '..')): 3314710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm new_comps.append(comp) 3324710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm elif new_comps: 3334710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm new_comps.pop() 3344710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm comps = new_comps 3354710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm path = slash.join(comps) 3364710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if initial_slashes: 3374710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm path = slash*initial_slashes + path 3384710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return path or dot 3394710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 3404710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 3414710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmdef abspath(path): 3424710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm """Return an absolute path.""" 3434710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if not isabs(path): 3444710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if isinstance(path, unicode): 3454710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm cwd = os.getcwdu() 3464710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm else: 3474710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm cwd = os.getcwd() 3484710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm path = join(cwd, path) 3494710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return normpath(path) 3504710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 3514710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 3524710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# Return a canonical path (i.e. the absolute location of a file on the 3534710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# filesystem). 3544710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 3554710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmdef realpath(filename): 3564710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm """Return the canonical path of the specified filename, eliminating any 3574710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmsymbolic links encountered in the path.""" 3584710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if isabs(filename): 3594710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm bits = ['/'] + filename.split('/')[1:] 3604710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm else: 3614710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm bits = [''] + filename.split('/') 3624710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 3634710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm for i in range(2, len(bits)+1): 3644710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm component = join(*bits[0:i]) 3654710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # Resolve symbolic links. 3664710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if islink(component): 3674710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm resolved = _resolve_link(component) 3684710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if resolved is None: 3694710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # Infinite loop -- return original component + rest of the path 3704710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return abspath(join(*([component] + bits[i:]))) 3714710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm else: 3724710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm newpath = join(*([resolved] + bits[i:])) 3734710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return realpath(newpath) 3744710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 3754710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return abspath(filename) 3764710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 3774710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 3784710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmdef _resolve_link(path): 3794710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm """Internal helper function. Takes a path and follows symlinks 3804710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm until we either arrive at something that isn't a symlink, or 3814710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm encounter a path we've seen before (meaning that there's a loop). 3824710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm """ 3834710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm paths_seen = set() 3844710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm while islink(path): 3854710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if path in paths_seen: 3864710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # Already seen this path, so we must have a symlink loop 3874710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return None 3884710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm paths_seen.add(path) 3894710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # Resolve where the link points to 3904710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm resolved = os.readlink(path) 3914710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if not isabs(resolved): 3924710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm dir = dirname(path) 3934710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm path = normpath(join(dir, resolved)) 3944710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm else: 3954710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm path = normpath(resolved) 3964710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return path 3974710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 3984710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmsupports_unicode_filenames = (sys.platform == 'darwin') 3994710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 4004710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmdef relpath(path, start=curdir): 4014710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm """Return a relative version of a path""" 4024710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 4034710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if not path: 4044710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm raise ValueError("no path specified") 4054710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 4064710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm start_list = [x for x in abspath(start).split(sep) if x] 4074710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm path_list = [x for x in abspath(path).split(sep) if x] 4084710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 4094710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # Work out how much of the filepath is shared by start and path. 4104710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm i = len(commonprefix([start_list, path_list])) 4114710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 4124710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm rel_list = [pardir] * (len(start_list)-i) + path_list[i:] 4134710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if not rel_list: 4144710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return curdir 4154710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return join(*rel_list) 416