ALib C++ Framework
by
Library Version: 2511 R0
Documentation generated by doxygen
Loading...
Searching...
No Matches
ALib Module Files - Programmer's Manual

1. Introduction

This ALib Module provides mechanics to scan directories and contained files. The scan results are collected in an instance of FTree, which inherits class StringTree. Using classes Cursor and StringTreeIterator, two very comfortable interfaces to accessing the results are available.

As of today, besides scanning files, no specific further functionality is given, and it is up to the user of the module to do with the result lists whatever is intended.

While the reference documentation of the types found in this module is quite verbose and thus should be all that is really needed, this Programmer's Manual just provides some few step-by-step demo samples.

2. Tutorial

2.1 Scanning a File Tree

A simple application needs to include just header ALib.Files.H.

#include "ALib.Files.H"
using namespace alib;
using namespace std;

For scanning a path including its subdirectories, a few objects are needed:

// Beginning of main(). Initialize ALIB once
alib::Bootstrap();
// The file tree to collect the results (using the shared, self-contained version).
SharedFTree fileTree(10);
// The scan parameters. Apart from the start directory, we leave everything on defaults.
ScanParameters scanParameters(ALIB_BASE_DIR A_PATH("/src/alib/files") );
// A vector to collect the result path(s).
files::CanonicalPathList resultPaths;

Here are the links to the reference documentation of these objects:

Note that the sample code above uses configuration macro ALIB_BASE_DIR, which is defined with the ALib unit test project, that this documentation uses to generate the samples.

That is all we needed to start the scan, which is done using the namespace function ScanFiles. Next we use namespace function DbgDump, which as its prefix Dbg indicates, is only available in debug-compilations of the library:

// Scan files. For this a full lock is needed.
{ALIB_LOCK_WITH(fileTree)
files::ScanFiles(*fileTree, scanParameters, &resultPaths);
}
// Dump files to the console. Lock in shared mode (read only)
AString dumpBuffer;
files::DbgDump(dumpBuffer, *fileTree);
}
cout << dumpBuffer << endl;

The resulting output is:

8--------- 0 root root 0B 03. Feb 2026 19:41 NON -- ( 0 D 0 F 0 EA 0BL) /
drwxr-xr-x 6 root root 4.0KiB 22. Jan 2026 13:54 NON -- ( 0 D 0 F 0 EA 0BL) /home
Lrwx------ 18 a a 4.0KiB 02. Oct 2025 07:12 RES -- ( 0 D 0 F 0 EA 0BL) /home/dev -> /mnt/a/dev
drwxr-xr-x 18 root root 4.0KiB 27. Sep 2025 09:02 NON -- ( 0 D 0 F 0 EA 0BL) /mnt
drwxr-xr-x 16 a a 4.0KiB 03. Dec 2025 12:14 NON -- ( 0 D 0 F 0 EA 0BL) /mnt/a
drwx------ 18 a a 4.0KiB 02. Oct 2025 07:12 NON -- ( 0 D 0 F 0 EA 0BL) /mnt/a/dev <- /home/dev
drwx------ 14 a a 4.0KiB 29. Jan 2026 19:20 NON -- ( 0 D 0 F 0 EA 0BL) /mnt/a/dev/A-Worx
drwxr-xr-x 9 a a 4.0KiB 03. Feb 2026 14:19 NON -- ( 0 D 0 F 0 EA 0BL) /mnt/a/dev/A-Worx/ALib
drwxr-xr-x 3 a a 4.0KiB 29. Jan 2026 19:56 NON -- ( 0 D 0 F 0 EA 0BL) /mnt/a/dev/A-Worx/ALib/src
drwxr--r-- 27 a a 4.0KiB 29. Jan 2026 19:56 NON -- ( 0 D 0 F 0 EA 0BL) /mnt/a/dev/A-Worx/ALib/src/alib
drwxr--r-- 3 a a 4.0KiB 03. Feb 2026 19:40 REC -- ( 1 D 15 F 0 EA 0BL) /mnt/a/dev/A-Worx/ALib/src/alib/files
-rw-r--r-- 1 a a 72.3KiB 03. Feb 2026 19:34 STA -- ( 0 D 0 F 0 EA 0BL) /mnt/a/dev/A-Worx/ALib/src/alib/files/fscanner.cpp
drwxr--r-- 2 a a 4.0KiB 01. Feb 2026 18:50 REC -- ( 0 D 3 F 0 EA 0BL) /mnt/a/dev/A-Worx/ALib/src/alib/files/expressions
-rw-r--r-- 1 a a 13.4KiB 28. Jan 2026 19:16 STA -- ( 0 D 0 F 0 EA 0BL) /mnt/a/dev/A-Worx/ALib/src/alib/files/expressions/fileexpressions.cpp
-rw-r--r-- 1 a a 11.9KiB 29. Jan 2026 19:56 STA -- ( 0 D 0 F 0 EA 0BL) /mnt/a/dev/A-Worx/ALib/src/alib/files/expressions/fileexpressions.inl
-rw-r--r-- 1 a a 3.0KiB 29. Jan 2026 19:56 STA -- ( 0 D 0 F 0 EA 0BL) /mnt/a/dev/A-Worx/ALib/src/alib/files/expressions/fileexpressions.mpp
-rw-r--r-- 1 a a 9.8KiB 03. Feb 2026 19:23 STA -- ( 0 D 0 F 0 EA 0BL) /mnt/a/dev/A-Worx/ALib/src/alib/files/filescamp.cpp
-rw-r--r-- 1 a a 17.2KiB 03. Feb 2026 19:33 STA -- ( 0 D 0 F 0 EA 0BL) /mnt/a/dev/A-Worx/ALib/src/alib/files/fscanner.inl
-rw-r--r-- 1 a a 60.9KiB 03. Feb 2026 19:40 STA -- ( 0 D 0 F 0 EA 0BL) /mnt/a/dev/A-Worx/ALib/src/alib/files/ftree.inl
-rw-r--r-- 1 a a 19.7KiB 03. Feb 2026 19:40 STA -- ( 0 D 0 F 0 EA 0BL) /mnt/a/dev/A-Worx/ALib/src/alib/files/file.cpp
-rw-r--r-- 1 a a 36.4KiB 03. Feb 2026 19:38 STA -- ( 0 D 0 F 0 EA 0BL) /mnt/a/dev/A-Worx/ALib/src/alib/files/finfo.inl
-rw-r--r-- 1 a a 3.7KiB 29. Jan 2026 19:56 STA -- ( 0 D 0 F 0 EA 0BL) /mnt/a/dev/A-Worx/ALib/src/alib/files/files.mpp
-rw-r--r-- 1 a a 1.7KiB 29. Jan 2026 19:56 STA -- ( 0 D 0 F 0 EA 0BL) /mnt/a/dev/A-Worx/ALib/src/alib/files/files.prepro.hpp
-rw-r--r-- 1 a a 3.9KiB 03. Feb 2026 19:24 STA -- ( 0 D 0 F 0 EA 0BL) /mnt/a/dev/A-Worx/ALib/src/alib/files/finfo.cpp
-rw-r--r-- 1 a a 12.4KiB 02. Feb 2026 22:23 STA -- ( 0 D 0 F 0 EA 0BL) /mnt/a/dev/A-Worx/ALib/src/alib/files/ftree.cpp
-rw-r--r-- 1 a a 2.9KiB 29. Jan 2026 19:56 STA -- ( 0 D 0 F 0 EA 0BL) /mnt/a/dev/A-Worx/ALib/src/alib/files/filescamp.inl
-rw-r--r-- 1 a a 2.7KiB 29. Jan 2026 19:56 STA -- ( 0 D 0 F 0 EA 0BL) /mnt/a/dev/A-Worx/ALib/src/alib/files/ffilter.inl

You might wonder about the resultPath vector given as an output parameter into function ScanFiles. Especially the question is: Why is it a vector? Wouldn't it be just the requested start path?

Let's quickly examine the result:

cout << "Number of result paths: " << resultPaths.size() << endl;
Path path;
resultPaths.front().AssemblePath(path); }
cout << " real path[0]: " << path << endl;

This writes:

Number of result paths: 1
real path[0]: /mnt/a/dev/A-Worx/ALib/src/alib/files

So, in fact, it is only one result, and it is here called "real path" and is exactly the path that was requested to be scanned. But this can be quite different when symbolic links come into place. More on this in the next chapter.

2.3 Real-Paths

2.3.1 The Symbolic Link Challenge

The invention of symbolic links in the Unix world allowed very flexible ways to organize directories and files. The drawback is, that software might be confused by such links, and many applications and tools exist do not handle symbolic links correctly. If done wrongly, circular references can easily occur and let a software, for example one that scans a file tree, run into an endless loop.

This library avoids this problem in the only possible efficient way: It always uses the real path of a file or directory. If a "real" directory is it twice, the recursion stops.

For this, the function ScanFiles defines a "data contract". Instead of repeating its definition here, we ask the reader to read about this here right now.

With this information in mind, we can now answer the question of why the result when scanning just one single path is a vector of paths! Here is a sample:

Suppose we have the following directory structure:
    /a/a 
    /b/b 
    /b/link -> /a/a

Scanning the directory /b leads to the following result paths:
    /a/a 
    /b/b 

So, one simple link into a sibling path of the start-path leads to two results already.

2.3.2 Reestablishing Symbolic Paths

The approach taken by the library to handle symbolic links is leads to 100% correct scan results, is extremely efficient in respect to other approaches of trying to detect cycles. Also, software that uses the result trees will not be confused by symbolic links and will never need to care about them.

However, at the moment software displays the scanned file's paths back to the user – or to other software, presenting real-paths can be a problem.

Take the sample of the tool AWorx DoxygenXLinks . Here, the writer of a C++ software documentation inserts cross-references into the text.

Note
Yes, the text you just read uses both: Doxygen and DoxygenXLinks, and yes, DoxygenXLinks scans the source files that contain the cross-references using the module ALib Files.

If the tool detects an erroneous cross-reference, it will report an error and make proposals on how to fix it. The error message contains the location of the cross-reference, including the source-file path along with the line and the column number. A developer's IDE can then open the source file by one mouse-click on the output (or keystroke "next error).<br> If the tool reports the real path, then the IDE would probably open the same source-file twice, once with the symbolic path (the one it knew before) and once with the real path! The IDE would maybe even ask: <em>"Do you want to edit files outside your project?"</em> To avoid this, class File offers a special parent node, accessible with
File::GetSymbolicParent. As its name suggests, this method returns the symbolic link that
the scanner followed to hit that file or directory. Custom scanners (or other code that manipulates a FTree) can use the method File::SetSymbolicParent to provide similar information. In the case that no symbolic link was followed, the method returns the same object that the code

    File ( myFile.AsCursor().Parent() )

would receive. Todo: ^^^^search and replace ".AsCursor().Parent()" with .GetSymbolicParent() in DXL and Cleaner

Consequently, class File offers two methods:

Note
It is also possible to directly use the StringTree's functionality provided with the method TCursor::AssemblePath. This can be accessed with:
  myFile.AsCursor().AssemblePath(...);

Here, of course, it is always the real path that is returned. If you can answer to yourself why this is, you have understood ALib's architecture in
respect to the classes StringTree / Cursor and FTree / File very well!

As a final remark: The function ScanFiles sets the symbolic parent only when the file or directory was not scanned already -either through the real path or a different symbolic link. This means that the symbolic parent is set only once and its setting depends on the order of the scanned files, and, in case of multiple scans, the order of their start paths.

2.3 Using Filters With Scanning

We left all fields of class ScanParameters with their default values in the previous sample. Now we want to look at fields:

Again, please refer to the reference documentation of the fields linked above, to get a quick understanding, why the scan function offers to set up to three different filter objects.

Class FFilter is a very simple virtual abstract interface class, which only has one single method Includes to implement. Derived filter types, need return true, if a file or directory "passes" the filter, hence in this case is included in the scan results.

It should be very straight forward to implement an own derived a filter class. The problem with such class would be, that it would be more or less "hard-coded" in respect to what is filtered and what not. This might be flexible enough for most applications.
The next chapter introduces a filter which is run-time compiled!

2.4 Class FileExpressions

In case module ALib Expressions is included in the ALib Build, this module ALib Files exposes the FileExpressions class, which implements a CompilerPlugin that allows articulate run-time expressions working with FInfo objects.

The class exposes the public inner type Filter which implements the FFilter interface. With construction, the filter accepts a character string containing the filter expression.

The full set of expression operators, functions and constants is documented with class FileExpressions and not to be repeated here. While expressions might return any kind of type, those used with class FileExpression::Filter, have to evaluate to a boolean value. As documented with module ALib Expressions, due to the type-safe implementation of the module, already at "compile time" of an expression (which is run-time of your software), the result type of an expression can be checked.

We just look at some samples:

We have to add the header-file ALib.Files.Expressions.H:

#include "ALib.Files.Expressions.H"

Now this code compiles:

// Beginning of main(). Initialize ALIB once
// objects needed for scanning files (using an automatic shared value)
SharedFTree fileTree(10); // 10 kb initial monotonic memory
fileTree.DbgCriticalSections(lang::Switch::Off); // we access this tree only from one thread
ScanParameters scanParameters(ALIB_BASE_DIR A_PATH("/src/alib/files") );
CanonicalPathList resultPaths;
// create the expression compiler and let it compile a filter
scanParameters.FileFilter= fex.CreateFilter(A_CHAR("name = \"files.mpp\""));
// Scan files
files::ScanFiles( *fileTree, scanParameters, &resultPaths);

The resulting output is:

8---------  0       root       root         0B 03. Feb 2026 19:41 NON -- (  0 D   0 F  0 EA  0BL) /   
drwxr-xr-x  6       root       root     4.0KiB 22. Jan 2026 13:54 NON -- (  0 D   0 F  0 EA  0BL) /home   
Lrwx------ 18          a          a     4.0KiB 02. Oct 2025 07:12 RES -- (  0 D   0 F  0 EA  0BL) /home/dev  -> /mnt/a/dev  
drwxr-xr-x 18       root       root     4.0KiB 27. Sep 2025 09:02 NON -- (  0 D   0 F  0 EA  0BL) /mnt   
drwxr-xr-x 16          a          a     4.0KiB 03. Dec 2025 12:14 NON -- (  0 D   0 F  0 EA  0BL) /mnt/a   
drwx------ 18          a          a     4.0KiB 02. Oct 2025 07:12 NON -- (  0 D   0 F  0 EA  0BL) /mnt/a/dev   <- /home/dev 
drwx------ 14          a          a     4.0KiB 29. Jan 2026 19:20 NON -- (  0 D   0 F  0 EA  0BL) /mnt/a/dev/A-Worx   
drwxr-xr-x  9          a          a     4.0KiB 03. Feb 2026 14:19 NON -- (  0 D   0 F  0 EA  0BL) /mnt/a/dev/A-Worx/ALib   
drwxr-xr-x  3          a          a     4.0KiB 29. Jan 2026 19:56 NON -- (  0 D   0 F  0 EA  0BL) /mnt/a/dev/A-Worx/ALib/src   
drwxr--r-- 27          a          a     4.0KiB 29. Jan 2026 19:56 NON -- (  0 D   0 F  0 EA  0BL) /mnt/a/dev/A-Worx/ALib/src/alib   
drwxr--r--  3          a          a     4.0KiB 03. Feb 2026 19:40 REC -- (  1 D   1 F  0 EA  0BL) /mnt/a/dev/A-Worx/ALib/src/alib/files   
drwxr--r--  2          a          a     4.0KiB 01. Feb 2026 18:50 REC -- (  0 D   0 F  0 EA  0BL) /mnt/a/dev/A-Worx/ALib/src/alib/files/expressions   
-rw-r--r--  1          a          a     3.7KiB 29. Jan 2026 19:56 STA -- (  0 D   0 F  0 EA  0BL) /mnt/a/dev/A-Worx/ALib/src/alib/files/files.mpp   

Here are some more samples:

scanParameters.FileFilter= fex.CreateFilter(A_CHAR("size > kilobytes(10)"));
8---------  0       root       root         0B 03. Feb 2026 19:41 NON -- (  0 D   0 F  0 EA  0BL) /   
drwxr-xr-x  6       root       root     4.0KiB 22. Jan 2026 13:54 NON -- (  0 D   0 F  0 EA  0BL) /home   
Lrwx------ 18          a          a     4.0KiB 02. Oct 2025 07:12 RES -- (  0 D   0 F  0 EA  0BL) /home/dev  -> /mnt/a/dev  
drwxr-xr-x 18       root       root     4.0KiB 27. Sep 2025 09:02 NON -- (  0 D   0 F  0 EA  0BL) /mnt   
drwxr-xr-x 16          a          a     4.0KiB 03. Dec 2025 12:14 NON -- (  0 D   0 F  0 EA  0BL) /mnt/a   
drwx------ 18          a          a     4.0KiB 02. Oct 2025 07:12 NON -- (  0 D   0 F  0 EA  0BL) /mnt/a/dev   <- /home/dev 
drwx------ 14          a          a     4.0KiB 29. Jan 2026 19:20 NON -- (  0 D   0 F  0 EA  0BL) /mnt/a/dev/A-Worx   
drwxr-xr-x  9          a          a     4.0KiB 03. Feb 2026 14:19 NON -- (  0 D   0 F  0 EA  0BL) /mnt/a/dev/A-Worx/ALib   
drwxr-xr-x  3          a          a     4.0KiB 29. Jan 2026 19:56 NON -- (  0 D   0 F  0 EA  0BL) /mnt/a/dev/A-Worx/ALib/src   
drwxr--r-- 27          a          a     4.0KiB 29. Jan 2026 19:56 NON -- (  0 D   0 F  0 EA  0BL) /mnt/a/dev/A-Worx/ALib/src/alib   
drwxr--r--  3          a          a     4.0KiB 03. Feb 2026 19:40 REC -- (  1 D   8 F  0 EA  0BL) /mnt/a/dev/A-Worx/ALib/src/alib/files   
-rw-r--r--  1          a          a    72.3KiB 03. Feb 2026 19:34 STA -- (  0 D   0 F  0 EA  0BL) /mnt/a/dev/A-Worx/ALib/src/alib/files/fscanner.cpp   
drwxr--r--  2          a          a     4.0KiB 01. Feb 2026 18:50 REC -- (  0 D   2 F  0 EA  0BL) /mnt/a/dev/A-Worx/ALib/src/alib/files/expressions   
-rw-r--r--  1          a          a    13.4KiB 28. Jan 2026 19:16 STA -- (  0 D   0 F  0 EA  0BL) /mnt/a/dev/A-Worx/ALib/src/alib/files/expressions/fileexpressions.cpp   
-rw-r--r--  1          a          a    11.9KiB 29. Jan 2026 19:56 STA -- (  0 D   0 F  0 EA  0BL) /mnt/a/dev/A-Worx/ALib/src/alib/files/expressions/fileexpressions.inl   
-rw-r--r--  1          a          a    17.2KiB 03. Feb 2026 19:33 STA -- (  0 D   0 F  0 EA  0BL) /mnt/a/dev/A-Worx/ALib/src/alib/files/fscanner.inl   
-rw-r--r--  1          a          a    60.9KiB 03. Feb 2026 19:40 STA -- (  0 D   0 F  0 EA  0BL) /mnt/a/dev/A-Worx/ALib/src/alib/files/ftree.inl   
-rw-r--r--  1          a          a    19.7KiB 03. Feb 2026 19:40 STA -- (  0 D   0 F  0 EA  0BL) /mnt/a/dev/A-Worx/ALib/src/alib/files/file.cpp   
-rw-r--r--  1          a          a    36.4KiB 03. Feb 2026 19:38 STA -- (  0 D   0 F  0 EA  0BL) /mnt/a/dev/A-Worx/ALib/src/alib/files/finfo.inl   
-rw-r--r--  1          a          a    12.4KiB 02. Feb 2026 22:23 STA -- (  0 D   0 F  0 EA  0BL) /mnt/a/dev/A-Worx/ALib/src/alib/files/ftree.cpp   

scanParameters.FileFilter= fex.CreateFilter(A_CHAR("GetHour(date) % 2 == 0"));
8---------  0       root       root         0B 03. Feb 2026 19:41 NON -- (  0 D   0 F  0 EA  0BL) /   
drwxr-xr-x  6       root       root     4.0KiB 22. Jan 2026 13:54 NON -- (  0 D   0 F  0 EA  0BL) /home   
Lrwx------ 18          a          a     4.0KiB 02. Oct 2025 07:12 RES -- (  0 D   0 F  0 EA  0BL) /home/dev  -> /mnt/a/dev  
drwxr-xr-x 18       root       root     4.0KiB 27. Sep 2025 09:02 NON -- (  0 D   0 F  0 EA  0BL) /mnt   
drwxr-xr-x 16          a          a     4.0KiB 03. Dec 2025 12:14 NON -- (  0 D   0 F  0 EA  0BL) /mnt/a   
drwx------ 18          a          a     4.0KiB 02. Oct 2025 07:12 NON -- (  0 D   0 F  0 EA  0BL) /mnt/a/dev   <- /home/dev 
drwx------ 14          a          a     4.0KiB 29. Jan 2026 19:20 NON -- (  0 D   0 F  0 EA  0BL) /mnt/a/dev/A-Worx   
drwxr-xr-x  9          a          a     4.0KiB 03. Feb 2026 14:19 NON -- (  0 D   0 F  0 EA  0BL) /mnt/a/dev/A-Worx/ALib   
drwxr-xr-x  3          a          a     4.0KiB 29. Jan 2026 19:56 NON -- (  0 D   0 F  0 EA  0BL) /mnt/a/dev/A-Worx/ALib/src   
drwxr--r-- 27          a          a     4.0KiB 29. Jan 2026 19:56 NON -- (  0 D   0 F  0 EA  0BL) /mnt/a/dev/A-Worx/ALib/src/alib   
drwxr--r--  3          a          a     4.0KiB 03. Feb 2026 19:40 REC -- (  1 D   1 F  0 EA  0BL) /mnt/a/dev/A-Worx/ALib/src/alib/files   
drwxr--r--  2          a          a     4.0KiB 01. Feb 2026 18:50 REC -- (  0 D   0 F  0 EA  0BL) /mnt/a/dev/A-Worx/ALib/src/alib/files/expressions   
-rw-r--r--  1          a          a    12.4KiB 02. Feb 2026 22:23 STA -- (  0 D   0 F  0 EA  0BL) /mnt/a/dev/A-Worx/ALib/src/alib/files/ftree.cpp   

scanParameters.FileFilter= fex.CreateFilter(A_CHAR("IndexOf(name,\"camp\")>0"));
8---------  0       root       root         0B 03. Feb 2026 19:41 NON -- (  0 D   0 F  0 EA  0BL) /   
drwxr-xr-x  6       root       root     4.0KiB 22. Jan 2026 13:54 NON -- (  0 D   0 F  0 EA  0BL) /home   
Lrwx------ 18          a          a     4.0KiB 02. Oct 2025 07:12 RES -- (  0 D   0 F  0 EA  0BL) /home/dev  -> /mnt/a/dev  
drwxr-xr-x 18       root       root     4.0KiB 27. Sep 2025 09:02 NON -- (  0 D   0 F  0 EA  0BL) /mnt   
drwxr-xr-x 16          a          a     4.0KiB 03. Dec 2025 12:14 NON -- (  0 D   0 F  0 EA  0BL) /mnt/a   
drwx------ 18          a          a     4.0KiB 02. Oct 2025 07:12 NON -- (  0 D   0 F  0 EA  0BL) /mnt/a/dev   <- /home/dev 
drwx------ 14          a          a     4.0KiB 29. Jan 2026 19:20 NON -- (  0 D   0 F  0 EA  0BL) /mnt/a/dev/A-Worx   
drwxr-xr-x  9          a          a     4.0KiB 03. Feb 2026 14:19 NON -- (  0 D   0 F  0 EA  0BL) /mnt/a/dev/A-Worx/ALib   
drwxr-xr-x  3          a          a     4.0KiB 29. Jan 2026 19:56 NON -- (  0 D   0 F  0 EA  0BL) /mnt/a/dev/A-Worx/ALib/src   
drwxr--r-- 27          a          a     4.0KiB 29. Jan 2026 19:56 NON -- (  0 D   0 F  0 EA  0BL) /mnt/a/dev/A-Worx/ALib/src/alib   
drwxr--r--  3          a          a     4.0KiB 03. Feb 2026 19:40 REC -- (  1 D   2 F  0 EA  0BL) /mnt/a/dev/A-Worx/ALib/src/alib/files   
drwxr--r--  2          a          a     4.0KiB 01. Feb 2026 18:50 REC -- (  0 D   0 F  0 EA  0BL) /mnt/a/dev/A-Worx/ALib/src/alib/files/expressions   
-rw-r--r--  1          a          a     9.8KiB 03. Feb 2026 19:23 STA -- (  0 D   0 F  0 EA  0BL) /mnt/a/dev/A-Worx/ALib/src/alib/files/filescamp.cpp   
-rw-r--r--  1          a          a     2.9KiB 29. Jan 2026 19:56 STA -- (  0 D   0 F  0 EA  0BL) /mnt/a/dev/A-Worx/ALib/src/alib/files/filescamp.inl   

scanParameters.FileFilter= fex.CreateFilter(A_CHAR("EndsWith(Path,\"files\")"));
8---------  0       root       root         0B 03. Feb 2026 19:41 NON -- (  0 D   0 F  0 EA  0BL) /   
drwxr-xr-x  6       root       root     4.0KiB 22. Jan 2026 13:54 NON -- (  0 D   0 F  0 EA  0BL) /home   
Lrwx------ 18          a          a     4.0KiB 02. Oct 2025 07:12 RES -- (  0 D   0 F  0 EA  0BL) /home/dev  -> /mnt/a/dev  
drwxr-xr-x 18       root       root     4.0KiB 27. Sep 2025 09:02 NON -- (  0 D   0 F  0 EA  0BL) /mnt   
drwxr-xr-x 16          a          a     4.0KiB 03. Dec 2025 12:14 NON -- (  0 D   0 F  0 EA  0BL) /mnt/a   
drwx------ 18          a          a     4.0KiB 02. Oct 2025 07:12 NON -- (  0 D   0 F  0 EA  0BL) /mnt/a/dev   <- /home/dev 
drwx------ 14          a          a     4.0KiB 29. Jan 2026 19:20 NON -- (  0 D   0 F  0 EA  0BL) /mnt/a/dev/A-Worx   
drwxr-xr-x  9          a          a     4.0KiB 03. Feb 2026 14:19 NON -- (  0 D   0 F  0 EA  0BL) /mnt/a/dev/A-Worx/ALib   
drwxr-xr-x  3          a          a     4.0KiB 29. Jan 2026 19:56 NON -- (  0 D   0 F  0 EA  0BL) /mnt/a/dev/A-Worx/ALib/src   
drwxr--r-- 27          a          a     4.0KiB 29. Jan 2026 19:56 NON -- (  0 D   0 F  0 EA  0BL) /mnt/a/dev/A-Worx/ALib/src/alib   
drwxr--r--  3          a          a     4.0KiB 03. Feb 2026 19:40 REC -- (  1 D  12 F  0 EA  0BL) /mnt/a/dev/A-Worx/ALib/src/alib/files   
-rw-r--r--  1          a          a    72.3KiB 03. Feb 2026 19:34 STA -- (  0 D   0 F  0 EA  0BL) /mnt/a/dev/A-Worx/ALib/src/alib/files/fscanner.cpp   
drwxr--r--  2          a          a     4.0KiB 01. Feb 2026 18:50 REC -- (  0 D   0 F  0 EA  0BL) /mnt/a/dev/A-Worx/ALib/src/alib/files/expressions   
-rw-r--r--  1          a          a     9.8KiB 03. Feb 2026 19:23 STA -- (  0 D   0 F  0 EA  0BL) /mnt/a/dev/A-Worx/ALib/src/alib/files/filescamp.cpp   
-rw-r--r--  1          a          a    17.2KiB 03. Feb 2026 19:33 STA -- (  0 D   0 F  0 EA  0BL) /mnt/a/dev/A-Worx/ALib/src/alib/files/fscanner.inl   
-rw-r--r--  1          a          a    60.9KiB 03. Feb 2026 19:40 STA -- (  0 D   0 F  0 EA  0BL) /mnt/a/dev/A-Worx/ALib/src/alib/files/ftree.inl   
-rw-r--r--  1          a          a    19.7KiB 03. Feb 2026 19:40 STA -- (  0 D   0 F  0 EA  0BL) /mnt/a/dev/A-Worx/ALib/src/alib/files/file.cpp   
-rw-r--r--  1          a          a    36.4KiB 03. Feb 2026 19:38 STA -- (  0 D   0 F  0 EA  0BL) /mnt/a/dev/A-Worx/ALib/src/alib/files/finfo.inl   
-rw-r--r--  1          a          a     3.7KiB 29. Jan 2026 19:56 STA -- (  0 D   0 F  0 EA  0BL) /mnt/a/dev/A-Worx/ALib/src/alib/files/files.mpp   
-rw-r--r--  1          a          a     1.7KiB 29. Jan 2026 19:56 STA -- (  0 D   0 F  0 EA  0BL) /mnt/a/dev/A-Worx/ALib/src/alib/files/files.prepro.hpp   
-rw-r--r--  1          a          a     3.9KiB 03. Feb 2026 19:24 STA -- (  0 D   0 F  0 EA  0BL) /mnt/a/dev/A-Worx/ALib/src/alib/files/finfo.cpp   
-rw-r--r--  1          a          a    12.4KiB 02. Feb 2026 22:23 STA -- (  0 D   0 F  0 EA  0BL) /mnt/a/dev/A-Worx/ALib/src/alib/files/ftree.cpp   
-rw-r--r--  1          a          a     2.9KiB 29. Jan 2026 19:56 STA -- (  0 D   0 F  0 EA  0BL) /mnt/a/dev/A-Worx/ALib/src/alib/files/filescamp.inl   
-rw-r--r--  1          a          a     2.7KiB 29. Jan 2026 19:56 STA -- (  0 D   0 F  0 EA  0BL) /mnt/a/dev/A-Worx/ALib/src/alib/files/ffilter.inl   

Note
Of course the expression compiler implemented with class FileExpressions may be used not only with filtering files. The compiler has public access and it can be used to compile and evaluate any other sort of expressions, including such that do not return a boolean value, can be compiled and evaluated.

3. Monitoring Changes in an FTree

Class FTree provides several interface methods that allow instances of abstract type FTreeListener to be registered for monitoring changes.

Those are:

For various reasons it is not - with reasonable effort and efficiency - possible to trigger the notification events from inside class FTree automatically. Besides this class being just a rather thin layer on top of class StringTree, the class itself can never be sure when, for example, a new file entry is really finally created with all available information set.

For this reason, the notification events have to be triggered by the code entities that manipulate the tree. Notification is performed by calling the method

with the according event type set.

Built-in scan functions duly perform such notifications. One warning has to be mentioned: If filter SPFileFilter DirectoryFilterPostRecursion is set, then notification about the creation of files, which later are removed by this filter will occur. On removal, only the node that is removed will be notified, but not the child nodes, which previously had been notified to having been created.
This is a design decision in favor of gaining efficiency.

4. Attaching Custom Data to Files

Class FTree allows attaching a custom object to each node. The memory of this custom object is allocated (and thus recycled with deletion of nodes) using the internal pool allocator.

It is up to the using software to keep track about which data type is assigned to which node of the tree. In the most common cases, where either all nodes receive the same data, or leaf-nodes (files) receive a different type than directories, this is no burden. With debug-compilations, type information is stored with every node and it is asserted that the same type is received or deleted that was previously set.

The interface provided to manage custom data is comprised by the following methods:

Once this is done, methods of class File:

A convenience method is furthermore provided with:

However, this method is only applicable if all nodes have custom data of the same type set.

5. Iterating File-Trees

TODO(251216 07:34): We need a new chapter here. StringTreeIterator has to be explained. An important point is that the iterator works on "cursor" level. To access the file data, one needs to do: File file( iterator.Node() ); Maybe a good sample is given with the DoxygenLinker project. We should pick snippets from there. Also explain the sorter here: It sorts the most recently modified files first.

6. Outlook

This should be enough for the time being. Module ALib Files is quite new and was introduced only with ALib C++ Framework release Version 2402 and was extended and overhauled with Version 2412. The future will show how this module expands.

Again, consult the extensive Reference Documentation for all details about the currently existing functionality.