fileutil_traverse(n)
π fileutil_traverse β the manual, but make it make sense
okay bestie, gather round, because we're talking about fileutil_traverse from the fileutil family (the manual page lives in section n, and it's the file utilities corner of the Tcllib world). this is iterative directory traversal and it is lowkey iconic. β¨
π¦ NAME π¦
fileutil_traverse β iterative directory traversal. that's it, that's the whole vibe. it walks your directory hierarchies for you so you don't have to. πΆβοΈπ
πΈ SYNOPSIS πΈ
package require Tcl 8.5 9
package require fileutil::traverse ?0.7?
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
like, look at her. so many ways to call her. main character energy fr fr. π
β¨ DESCRIPTION β¨
so this package hands you objects for doing programmable traversal of directory hierarchies. not just "list me the files", no ma'am β you get to program it. π§
the main command the package exports is this one:
::fileutil::traverse ?objectName? path ?option value...?β this creates a brand new traversal object, and it comes with its own global Tcl command whose name is objectName. you use that command to do stuff to the traverser. and here's the cute part: if you pass the string%AUTO%as the objectName, the package just makes up a unique name for you. no thoughts, head empty, name generated. π
about the options it recognizes β scroll down to the OPTIONS section, bestie. but important: all of those options can only be set during the creation of the traversal object. changing them later? not possible. attempting it throws errors. it's giving "you had one chance and you used it." π
the object command has this general shape:
$traverser command ?arg arg ...?
the command plus its arguments decide exactly what the object does. every time. periodt.
and here are the commands a traversal object can do:
$traverser filesβ the most high-level method of the bunch. invoke it and you get back a list of the names of all files and directories matching the traverser's current configuration. one call, whole list, slay. πβ¨$traverser foreach filevar scriptβ the high-levelfilesmethod above is literally built on top of this mid-level one. invoke it and it finds everything matching the current config, then runs script for each path. the path currently being looked at gets stored in the variable named by filevar. and get this: both the variable and the script live in / are executed in the context of the caller of the method. infiles, the script's whole job is just saving the found paths into the list that gets returned. humble but crucial. π«Ά$traverser next filevarβ the lowest-level interface to the traverser, the core that every higher method is built on. invoke it and it returns a boolean: did it find a path matching the current config (True) or not (False)? if it did find one, that path is stored into the variable named by filevar, in the context of the caller.
the foreach method is literally just calling this one in a loop until it returns False. it's exposed so that you can also incrementally traverse a directory hierarchy in an event-based manner. yes, that's a real capability. yes, it's cool. π
π¨ okay important note, listen up: the traverser does follow symbolic links β except when doing so would make it enter a link-cycle. in other words, she takes care not to lose herself in infinite loops when she runs into circular link structures. she is self-aware. π but also note: even links that are not followed will still appear in the result. so they show up, they just don't get chased. noted. π
π OPTIONS π
-prefiltercommand_prefix β this callback runs for directories. its result decides whether the traverser recurses into that directory or not. default behaviour is to always recurse into all directories (she's trusting like that). the callback gets invoked with a single argument β the absolute path of the directory β and it has to return a boolean value: True when the directory passes the filter, False when it doesn't. πͺβ¨-filtercommand_prefix β this callback runs for all paths. its result decides whether the current path is a valid result and gets returned bynext. default is to accept all paths as valid (no gatekeeping here). the callback is invoked with a single argument, the absolute path to check, and must return a boolean: True when the path passes the filter, False when it doesn't. π΅οΈβοΈ-errorcmdcommand_prefix β this callback runs for all paths the traverser has trouble with. like, she couldn't change into them, couldn't get their status, etc. default is to just ignore any such problems (we love a chill queen). the callback is invoked with two arguments: the absolute path where the error occurred, and the error message. errors thrown by the filter callbacks get handled through this callback too. but heads up: errors thrown by the error callback itself are not caught and ignored β they're allowed to pass to the caller, i.e. however invoked thenext. and any other results from the callback? ignored. π«
π WARNINGS AND INCOMPATIBILITIES π
0.4.4β in this version, the traverser's broken system for handling symlinks was replaced with one that works correctly and properly enumerates all the legal non-cyclic paths under a base directory. glow-up complete. β¨
and while it's correct now, it also means 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(n) because of its brokenness. so yeah, correctness has a price tag. π
a concrete example, and honestly an extreme case: 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 this:
/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 you have to handle a hierarchy this pathological, the recommendation is to use the -prefilter option to stop the traverser from following symbolic links. like so, bestie:
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
look at that. filter says "no links, we're not doing that today." iconic. π
π BUGS, IDEAS, FEEDBACK π
this document, and the package it describes, will undoubtedly contain bugs and other problems. like, obviously. it's software. please report such in the category fileutil of the Tcllib Trackers at http://core.tcl.tk/tcllib/reportlist. and please also report any ideas for enhancements you may have for either the package and/or the documentation β we want them, fr fr. π
when proposing code changes, please provide unified diffs, i.e. the output of diff -u. that's the format. don't be mysterious about it. π
and 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. yeah, that button. the left-most one. you got this. π«Ά
π KEYWORDS π
- directory traversal
- traversal
(short list, big responsibilities.) π
π CATEGORY π
Programming tools π οΈβ¨
and that's the whole page, bestie!! this beauty is from tcllib, version 0.7, dated per the page footer β so go forth, traverse those directories, follow those symlinks responsibly (or don't, use -prefilter), and remember: she does not lose herself in infinite loops. be more like her. mwah. πππ¦πΈπ
π¦ where this page comes from
- fedora 43: tcllib 2.0-3.fc43 Β· TCL
- fedora 44: tcllib 2.0-4.fc44 Β· TCL
- nixos 26.05: tcllib 2.0
- nixpkgs unstable: tcllib 2.0
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms