fileutil_traverse(3tcl) file utilities fileutil_traverse(3tcl)
______________________________________________________________________________
NAME
fileutil_traverse - Iterative directory traversal
SYNOPSIS
package require Tcl 8.3
package require fileutil::traverse ?0.6?
package require fileutil
package require control
::fileutil::traverse ?objectName? path ?option value...?
$traverser command ?arg arg ...?
$traverser files
$traverser foreach filevar script
$traverser next filevar
______________________________________________________________________________
DESCRIPTION
This package provides objects for the programmable traversal of direc-
tory hierarchies. The main command exported by the package is:
::fileutil::traverse ?objectName? path ?option value...?
The command creates a new traversal object with an associated
global Tcl command whose name is objectName. This command may be
used to invoke various operations on the traverser. If the
string %AUTO% is used as the objectName then a unique name will
be generated by the package itself.
Regarding the recognized options see section OPTIONS. Note that
all these options can be set only during the creation of the
traversal object. Changing them later is not possible and causes
errors to be thrown if attempted.
The object command has the following general form:
$traverser command ?arg arg ...?
Command and its arguments determine the exact behavior of
the object.
The following commands are possible for traversal objects:
$traverser files
This method is the most highlevel one provided by traversal ob-
jects. When invoked it returns a list containing the names of
all files and directories matching the current configuration of
the traverser.
$traverser foreach filevar script
The highlevel files method (see above) is based on this mid-
level method. When invoked it finds all files and directories
matching per the current configuration and executes the script
for each path. The current path under consideration is stored in
the variable named by filevar. Both variable and script live /
are executed in the context of the caller of the method. In the
method files the script simply saves the found paths into the
list to return.
$traverser next filevar
This is the lowest possible interface to the traverser, the core
all higher methods are built on. When invoked it returns a bool-
ean value indicating whether it found a path matching the cur-
rent configuration (True), or not (False). If a path was found
it is stored into the variable named by filevar, in the context
of the caller.
The foreach method simply calls this method in a loop until it
returned False. This method is exposed so that we are also able
to incrementally traverse a directory hierarchy in an event-
based manner.
Note that the traverser does follow symbolic links, except when
doing so would cause it to enter a link-cycle. In other words,
the command takes care to not lose itself in infinite loops upon
encountering circular link structures. Note that even links
which are not followed will still appear in the result.
OPTIONS
-prefilter command_prefix
This callback is executed for directories. Its result determines
if the traverser recurses into the directory or not. The default
is to always recurse into all directories. The callback is in-
voked with a single argument, the absolute path of the direc-
tory, and has to return a boolean value, True when the directory
passes the filter, and False if not.
-filter command_prefix
This callback is executed for all paths. Its result determines
if the current path is a valid result, and returned by next. The
default is to accept all paths as valid. The callback is invoked
with a single argument, the absolute path to check, and has to
return a boolean value, True when the path passes the filter,
and False if not.
-errorcmd command_prefix
This callback is executed for all paths the traverser has trou-
ble with. Like being unable to change into them, get their sta-
tus, etc. The default is to ignore any such problems. The call-
back is invoked with a two arguments, the absolute path for
which the error occured, and the error message. Errors thrown by
the filter callbacks are handled through this callback too. Er-
rors thrown by the error callback itself are not caught and ig-
nored, but allowed to pass to the caller, i.e. however invoked
the next. Any other results from the callback are ignored.
WARNINGS AND INCOMPATIBILITIES
0.4.4 In this version the traverser's broken system for handling sym-
links was replaced with one working correctly and properly enu-
merating all the legal non-cyclic paths under a base directory.
While correct this means that certain pathological directory hi-
erarchies with cross-linked sym-links will now take about
O(n**2) time to enumerate whereas the original broken code man-
aged O(3tcl) due to its brokenness.
A concrete example and extreme case is the "/sys" hierarchy un-
der Linux where some hundred devices exist under both "/sys/de-
vices" and "/sys/class" with the two sub-hierarchies linking to
the other, generating millions of legal paths to enumerate. The
structure, reduced to three devices, roughly looks like
/sys/class/tty/tty0 --> ../../dev/tty0
/sys/class/tty/tty1 --> ../../dev/tty1
/sys/class/tty/tty2 --> ../../dev/tty1
/sys/dev/tty0/bus
/sys/dev/tty0/subsystem --> ../../class/tty
/sys/dev/tty1/bus
/sys/dev/tty1/subsystem --> ../../class/tty
/sys/dev/tty2/bus
/sys/dev/tty2/subsystem --> ../../class/tty
When having to handle such a pathological hierarchy it is recommended
to use the -prefilter option to prevent the traverser from following
symbolic links, like so:
package require fileutil::traverse
proc NoLinks {fileName} {
if {[string equal [file type $fileName] link]} {
return 0
}
return 1
}
fileutil::traverse T /sys/devices -prefilter NoLinks
T foreach p {
puts $p
}
T destroy
BUGS, IDEAS, FEEDBACK
This document, and the package it describes, will undoubtedly contain
bugs and other problems. Please report such in the category fileutil
of the Tcllib Trackers [http://core.tcl.tk/tcllib/reportlist]. Please
also report any ideas for enhancements you may have for either package
and/or documentation.
When proposing code changes, please provide unified diffs, i.e the out-
put of diff -u.
Note further that attachments are strongly preferred over inlined
patches. Attachments can be made by going to the Edit form of the
ticket immediately after its creation, and then using the left-most
button in the secondary navigation bar.
KEYWORDS
directory traversal, traversal
CATEGORY
Programming tools
tcllib 0.6 fileutil_traverse(3tcl)