A Java library providing glob pattern matching traversal of the file system. In addition to pattern matching, Git ignore files can be honored.
The library is available from Maven Central using the following Maven dependency:
<dependency>
<groupId>org.cthing</groupId>
<artifactId>filevisitor</artifactId>
<version>2.0.0</version>
</dependency>
or the following Gradle dependency:
implementation("org.cthing:filevisitor:2.0.0")
In a similar manner to Files.walkFileTree,
the MatchingTreeWalker
will traverse the file system starting at the specified directory. The walker will attempt
to match files and directories against the patterns specified (see Pattern Matching Syntax).
Specify an implementation of the MatchHandler
interface to process the matched files and directories. The following
example looks for all Java files:
final MatchHandler handler = new MyMatchHandler();
final MatchingTreeWalker walker = new MatchingTreeWalker(start, handler, "**/*.java");
walker.walk();
To use Files.walkFileTree
directly, specify an instance of the MatchingFileVisitor
. The equivalent to the above example is:
final MatchHandler handler = new MyMatchHandler();
final MatchingFileVisitor visitor = new MatchingFileVisitor(handler, "**/*.java");
Files.walkFileTree(start, visitor);
To obtain a list of all matched files and directories, use the CollectingMatchHandler
.
final CollectingMatchHandler handler = new CollectingMatchHandler();
new MatchingTreeWalker(start, handler, "**/*.java").walk();
final List<Path> matchedPaths = handler.getPaths();
To obtain a list of only matched files:
final CollectingMatchHandler handler = new CollectingMatchHandler(false);
new MatchingTreeWalker(start, handler, "**/*.java").walk();
final List<Path> matchedPaths = handler.getPaths();
Patterns to match files and directories use the Git ignore
glob syntax. Note that unlike Git ignore globs, which indicate the files and directories to exclude, in this
library, they indicate the files and directories to include. For example, specifying **/*.java
includes
all Java files in any directory. To exclude files and directories, use the "!" negation prefix. Below is summary
of the glob syntax. See the Git ignore documentation for a
detailed explanation.
- Blank lines are ignored
- Lines starting with "#" are comments
- A "!" prefix negates the pattern
- A "" escapes special characters (e.g. to use a "#" character, specify "\#")
- A "/" is used as the directory separator regardless of the platform
- A "/" at the end of the pattern only matches directories
- Relative paths are resolved against the starting directory of the traversal
- A "*" matches anything except a slash
- A "?" matches any one character except a slash
- Range notation (e.g. "[a-zA-Z]") can be used to match one character in that range
- A leading "*/" (e.g. "*/foo") matches in all directories
- A trailing "/**" (e.g. "foo/**") matches everything inside
- A slash followed by two consecutive asterisks followed by a slash (e.g. "a/**/b") matches zero or more directories
By default, file tree traversal respects Git ignore files. If the start directory is anywhere within a Git work tree, any Git ignore files will be used to exclude files from matching. Global Git ignore files are also considered. Git ignore files have the same precedence as they do in Git. User specified match patterns have higher precedence than Git ignore patterns.
To disable the use of Git ignore files, call the MatchingTreeWalker.respectGitignore
or
MatchingFileVisitor.respectGitignore
method with false
.
Hidden Files
By default, file tree traversal ignores hidden files and directories. To include hidden files and directories, call
the MatchingTreeWalker.excludeHidden
or MatchingFileVisitor.excludeHidden
method with false
.
By default, the MatchingTreeWalker
does not follow symbolic links. To follow symbolic links, call the
MatchingTreeWalker.followLinks
method with true
.
By default, the MatchingTreeWalker
performs a depth first traversal of the entire file tree under the starting
directory. To restrict the traversal to a specific depth, call the MatchingTreeWalker.maxDepth
method. Specify,
Integer.MAX_VALUE
for unlimited depth.
The glob and Git ignore pattern parsing and matching in this library is based on the Rust code in the ripgrep project's globset and ignore crates covered by the Unlicense (i.e. public domain).
The Git config file parser is a heavily modified copy of the Config class from the Eclipse JGitTM project and is covered by the EDL license.
The library is compiled for Java 17. If a Java 17 toolchain is not available, one will be downloaded.
Gradle is used to build the library:
./gradlew build
The Javadoc for the library can be generated by running:
./gradlew javadoc
This project is released on the Maven Central repository. Perform the following steps to create a release.
- Commit all changes for the release
- In the
build.gradle.kts
file, edit theProjectVersion
object- Set the version for the release. The project follows semantic versioning.
- Set the build type to
BuildType.release
- Commit the changes
- Wait until CI builds the release candidate
- Run the command
mkrelease filevisitor <version>
- In a browser go to the Maven Central Repository Manager
- Log in
- Use the
Staging Upload
to upload the generated artifact bundlefilevisitor-bundle-<version>.jar
- Click on
Staging Repositories
- Once it is enabled, press
Release
to release the artifacts to Maven Central - Log out
- Wait for the new release to be available on Maven Central
- In a browser, go to the project on GitHub
- Generate a release with the tag
<version>
- In the build.gradle.kts file, edit the
ProjectVersion
object- Increment the version patch number
- Set the build type to
BuildType.snapshot
- Update the
CHANGELOG.md
with the changes in the release and prepare for next release changes - Update the
Usage
section in theREADME.md
with the latest artifact release version - Commit these changes