fileutil_traverse(3tcl) | file utilities | fileutil_traverse(3tcl) |
fileutil_traverse - Iterative directory traversal
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
This package provides objects for the programmable traversal of directory hierarchies. The main command exported by the package is:
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:
The following commands are possible for traversal objects:
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.
While correct this means that certain pathological directory hierarchies with cross-linked sym-links will now take about O(n**2) time to enumerate whereas the original broken code managed O(3tcl) due to its brokenness.
A concrete example and extreme case is the "/sys" hierarchy under Linux where some hundred devices exist under both "/sys/devices" 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
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 output 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.
directory traversal, traversal
Programming tools
0.6 | tcllib |