blob: 456743cff2fc02b7981947424910ea5feb2c6d47 [file] [log] [blame]
Guido van Rossumc6360141990-10-13 19:23:40 +00001# Module 'path' -- common operations on POSIX pathnames
2
3import posix
Guido van Rossum40d93041990-10-21 16:17:34 +00004import stat
Guido van Rossumc6360141990-10-13 19:23:40 +00005
6
Guido van Rossum4d0fdc31991-08-16 13:27:58 +00007# Join two pathnames.
8# Insert a '/' unless the first part is empty or already ends in '/'.
9# Ignore the first part altogether if the second part is absolute
Guido van Rossumc6360141990-10-13 19:23:40 +000010# (begins with '/').
11#
Guido van Rossum4d0fdc31991-08-16 13:27:58 +000012def join(a, b):
Guido van Rossumc6360141990-10-13 19:23:40 +000013 if b[:1] = '/': return b
14 if a = '' or a[-1:] = '/': return a + b
Guido van Rossum4d0fdc31991-08-16 13:27:58 +000015 # Note: join('x', '') returns 'x/'; is this what we want?
Guido van Rossumc6360141990-10-13 19:23:40 +000016 return a + '/' + b
17
18
Guido van Rossum4d0fdc31991-08-16 13:27:58 +000019cat = join # For compatibility
20
21
Guido van Rossumc6360141990-10-13 19:23:40 +000022# Split a path in head (empty or ending in '/') and tail (no '/').
23# The tail will be empty if the path ends in '/'.
Guido van Rossum4d0fdc31991-08-16 13:27:58 +000024# It is always true that head+tail = p.
Guido van Rossumc6360141990-10-13 19:23:40 +000025#
26def split(p):
27 head, tail = '', ''
28 for c in p:
29 tail = tail + c
30 if c = '/':
31 head, tail = head + tail, ''
32 return head, tail
33
34
Guido van Rossum4d0fdc31991-08-16 13:27:58 +000035# Split a path in root and extension.
36# The extension is everything starting at the first dot in the last
37# pathname component; the root is everything before that.
38# It is always true that root+ext = p.
39#
40def splitext(p):
41 root, ext = '', ''
42 for c in p:
43 if c = '/':
44 root, ext = root + ext + c, ''
45 elif c = '.' or ext:
46 ext = ext + c
47 else:
48 root = root + c
49 return root, ext
50
51
Guido van Rossumc6360141990-10-13 19:23:40 +000052# Return the tail (basename) part of a path.
53#
54def basename(p):
55 return split(p)[1]
56
57
58# Return the longest prefix of all list elements.
59#
60def commonprefix(m):
61 if not m: return ''
62 prefix = m[0]
63 for item in m:
64 for i in range(len(prefix)):
65 if prefix[:i+1] <> item[:i+1]:
66 prefix = prefix[:i]
67 if i = 0: return ''
68 break
69 return prefix
70
71
72# Does a file/directory exist?
73#
74def exists(path):
75 try:
76 st = posix.stat(path)
77 except posix.error:
78 return 0
79 return 1
80
81
82# Is a path a posix directory?
83#
84def isdir(path):
85 try:
86 st = posix.stat(path)
87 except posix.error:
88 return 0
Guido van Rossum40d93041990-10-21 16:17:34 +000089 return stat.S_ISDIR(st[stat.ST_MODE])
Guido van Rossumc6360141990-10-13 19:23:40 +000090
91
92# Is a path a symbolic link?
93# This will always return false on systems where posix.lstat doesn't exist.
94#
95def islink(path):
96 try:
97 st = posix.lstat(path)
98 except (posix.error, NameError):
99 return 0
Guido van Rossum40d93041990-10-21 16:17:34 +0000100 return stat.S_ISLNK(st[stat.ST_MODE])
Guido van Rossumc6360141990-10-13 19:23:40 +0000101
102
103_mounts = []
104
105def _getmounts():
106 import commands, string
107 mounts = []
108 data = commands.getoutput('/etc/mount')
109 lines = string.splitfields(data, '\n')
110 for line in lines:
111 words = string.split(line)
112 if len(words) >= 3 and words[1] = 'on':
113 mounts.append(words[2])
114 return mounts
115
116
117# Is a path a mount point?
118# This only works for normalized, absolute paths,
119# and only if the mount table as printed by /etc/mount is correct.
120# Sorry.
121#
122def ismount(path):
123 if not _mounts:
124 _mounts[:] = _getmounts()
125 return path in _mounts
126
127
128# Directory tree walk.
129# For each directory under top (including top itself),
130# func(arg, dirname, filenames) is called, where dirname
131# is the name of the directory and filenames is the list of
132# files (and subdirectories etc.) in the directory.
133# func may modify the filenames list, to implement a filter,
134# or to impose a different order of visiting.
135#
136def walk(top, func, arg):
137 try:
138 names = posix.listdir(top)
139 except posix.error:
140 return
141 func(arg, top, names)
142 exceptions = ('.', '..')
143 for name in names:
144 if name not in exceptions:
Guido van Rossum4d0fdc31991-08-16 13:27:58 +0000145 name = join(top, name)
Guido van Rossumc6360141990-10-13 19:23:40 +0000146 if isdir(name):
147 walk(name, func, arg)