bionic (3) traverse.3tcl.gz

Provided by: tcllib_1.19-dfsg-2_all bug

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 directory 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 objects. 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 boolean value indicating whether it found a path matching the current
              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
              invoked with a single argument, the absolute path of the directory, 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  trouble  with.  Like  being  unable  to
              change  into them, get their status, etc. The default is to ignore any such problems. The callback
              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. Errors
              thrown by the error callback itself are not caught and ignored, 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 symlinks was replaced with one working
              correctly and properly enumerating all the legal non-cyclic paths under a base directory.

              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

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 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.

KEYWORDS

       directory traversal, traversal

CATEGORY

       Programming tools