1fileutil_traverse(n) file utilities fileutil_traverse(n)
2
3
4
5______________________________________________________________________________
6
8 fileutil_traverse - Iterative directory traversal
9
11 package require Tcl 8.3
12
13 package require fileutil::traverse ?0.6?
14
15 package require fileutil
16
17 package require control
18
19 ::fileutil::traverse ?objectName? path ?option value...?
20
21 $traverser command ?arg arg ...?
22
23 $traverser files
24
25 $traverser foreach filevar script
26
27 $traverser next filevar
28
29______________________________________________________________________________
30
32 This package provides objects for the programmable traversal of direc‐
33 tory hierarchies. The main command exported by the package is:
34
35 ::fileutil::traverse ?objectName? path ?option value...?
36 The command creates a new traversal object with an associated
37 global Tcl command whose name is objectName. This command may be
38 used to invoke various operations on the traverser. If the
39 string %AUTO% is used as the objectName then a unique name will
40 be generated by the package itself.
41
42 Regarding the recognized options see section OPTIONS. Note that
43 all these options can be set only during the creation of the
44 traversal object. Changing them later is not possible and causes
45 errors to be thrown if attempted.
46
47 The object command has the following general form:
48
49 $traverser command ?arg arg ...?
50 Command and its arguments determine the exact behavior of
51 the object.
52
53 The following commands are possible for traversal objects:
54
55 $traverser files
56 This method is the most highlevel one provided by traversal ob‐
57 jects. When invoked it returns a list containing the names of
58 all files and directories matching the current configuration of
59 the traverser.
60
61 $traverser foreach filevar script
62 The highlevel files method (see above) is based on this mid-
63 level method. When invoked it finds all files and directories
64 matching per the current configuration and executes the script
65 for each path. The current path under consideration is stored in
66 the variable named by filevar. Both variable and script live /
67 are executed in the context of the caller of the method. In the
68 method files the script simply saves the found paths into the
69 list to return.
70
71 $traverser next filevar
72 This is the lowest possible interface to the traverser, the core
73 all higher methods are built on. When invoked it returns a bool‐
74 ean value indicating whether it found a path matching the cur‐
75 rent configuration (True), or not (False). If a path was found
76 it is stored into the variable named by filevar, in the context
77 of the caller.
78
79 The foreach method simply calls this method in a loop until it
80 returned False. This method is exposed so that we are also able
81 to incrementally traverse a directory hierarchy in an event-
82 based manner.
83
84 Note that the traverser does follow symbolic links, except when
85 doing so would cause it to enter a link-cycle. In other words,
86 the command takes care to not lose itself in infinite loops upon
87 encountering circular link structures. Note that even links
88 which are not followed will still appear in the result.
89
91 -prefilter command_prefix
92 This callback is executed for directories. Its result determines
93 if the traverser recurses into the directory or not. The default
94 is to always recurse into all directories. The callback is in‐
95 voked with a single argument, the absolute path of the direc‐
96 tory, and has to return a boolean value, True when the directory
97 passes the filter, and False if not.
98
99 -filter command_prefix
100 This callback is executed for all paths. Its result determines
101 if the current path is a valid result, and returned by next. The
102 default is to accept all paths as valid. The callback is invoked
103 with a single argument, the absolute path to check, and has to
104 return a boolean value, True when the path passes the filter,
105 and False if not.
106
107 -errorcmd command_prefix
108 This callback is executed for all paths the traverser has trou‐
109 ble with. Like being unable to change into them, get their sta‐
110 tus, etc. The default is to ignore any such problems. The call‐
111 back is invoked with a two arguments, the absolute path for
112 which the error occured, and the error message. Errors thrown by
113 the filter callbacks are handled through this callback too. Er‐
114 rors thrown by the error callback itself are not caught and ig‐
115 nored, but allowed to pass to the caller, i.e. however invoked
116 the next. Any other results from the callback are ignored.
117
119 0.4.4 In this version the traverser's broken system for handling sym‐
120 links was replaced with one working correctly and properly enu‐
121 merating all the legal non-cyclic paths under a base directory.
122
123 While correct this means that certain pathological directory hi‐
124 erarchies with cross-linked sym-links will now take about
125 O(n**2) time to enumerate whereas the original broken code man‐
126 aged O(n) due to its brokenness.
127
128 A concrete example and extreme case is the "/sys" hierarchy un‐
129 der Linux where some hundred devices exist under both "/sys/de‐
130 vices" and "/sys/class" with the two sub-hierarchies linking to
131 the other, generating millions of legal paths to enumerate. The
132 structure, reduced to three devices, roughly looks like
133
134
135 /sys/class/tty/tty0 --> ../../dev/tty0
136 /sys/class/tty/tty1 --> ../../dev/tty1
137 /sys/class/tty/tty2 --> ../../dev/tty1
138
139 /sys/dev/tty0/bus
140 /sys/dev/tty0/subsystem --> ../../class/tty
141 /sys/dev/tty1/bus
142 /sys/dev/tty1/subsystem --> ../../class/tty
143 /sys/dev/tty2/bus
144 /sys/dev/tty2/subsystem --> ../../class/tty
145
146
147 When having to handle such a pathological hierarchy it is recommended
148 to use the -prefilter option to prevent the traverser from following
149 symbolic links, like so:
150
151
152 package require fileutil::traverse
153
154 proc NoLinks {fileName} {
155 if {[string equal [file type $fileName] link]} {
156 return 0
157 }
158 return 1
159 }
160
161 fileutil::traverse T /sys/devices -prefilter NoLinks
162 T foreach p {
163 puts $p
164 }
165 T destroy
166
167
169 This document, and the package it describes, will undoubtedly contain
170 bugs and other problems. Please report such in the category fileutil
171 of the Tcllib Trackers [http://core.tcl.tk/tcllib/reportlist]. Please
172 also report any ideas for enhancements you may have for either package
173 and/or documentation.
174
175 When proposing code changes, please provide unified diffs, i.e the out‐
176 put of diff -u.
177
178 Note further that attachments are strongly preferred over inlined
179 patches. Attachments can be made by going to the Edit form of the
180 ticket immediately after its creation, and then using the left-most
181 button in the secondary navigation bar.
182
184 directory traversal, traversal
185
187 Programming tools
188
189
190
191tcllib 0.6 fileutil_traverse(n)