Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 6 additions & 8 deletions .github/workflows/go.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,13 @@

#
# Created: 18th August 2025
# Updated: 19th August 2026
# Updated: 3rd September 2026
#

name: Go

env:
GO_MIN_VERSION: '1.21'
GO_MIN_VERSION: '1.23'
VERBOSITY: 1

on:
Expand All @@ -32,7 +32,9 @@ jobs:

build:
strategy:
# Set fail-fast to false to ensure that feedback is delivered for all matrix combinations. Consider changing this to true when your workflow is stable.
# Set fail-fast to false to ensure that feedback is delivered for all
# matrix combinations. Consider changing this to true when your
# workflow is stable.
fail-fast: false

matrix:
Expand All @@ -41,8 +43,6 @@ jobs:
- '1.25'
- '1.24'
- '1.23'
- '1.22'
- '1.21'
os:
- macos-latest
- ubuntu-latest
Expand All @@ -69,7 +69,6 @@ jobs:

lint:
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v4

Expand All @@ -78,8 +77,7 @@ jobs:
with:
go-version: '${{ env.GO_MIN_VERSION }}'

- name: "Run golangci-lint"
- name: "golangci-lint"
uses: golangci/golangci-lint-action@v6
with:
args: --fast
verify: false
2 changes: 1 addition & 1 deletion .sis/script_info_lines.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
recls.Go is a platform-independent recursive file-system search library for Go
Copyright (c) 2019-2024, Matthew Wilson and Synesis Information Systems
Copyright (c) 2019-2026, Matthew Wilson and Synesis Information Systems
Copyright (c) 2015-2019, Matthew Wilson and Synesis Software
32 changes: 14 additions & 18 deletions CHANGES.md
Original file line number Diff line number Diff line change
@@ -1,28 +1,24 @@
# recls.Go - Changes <!-- omit in toc -->


## 0.0.2 - 2nd September 2026

* updated dependencies;

## 0.1.0-alpha1 - 3rd September 2026

## 0.0.1 - 20th August 2026
* First functional file-system search release (recls2-shaped);
* Added **Entry**, **Stat**, **Search** / **SearchFunc** (DFS, `iter.Seq2`);
* **Search** / **SearchFunc** accept **`PatternSource`** (`string | []string`);
* Path fields from **libpath.Go** `PathDescriptor`; patterns via **shwild.Go**;
* Core search flags: type filter, recursive, hidden, access failure, symlinks,
infinite-loop guard, mark-dirs, details-later, tilde-on-empty-root;
* Unit and component tests; examples **hard_links**, **libver**, **rls**,
**search_simple**, **stat**;
* **Entry.LinkCount** (Unix `Stat_t.Nlink`; Windows `BY_HANDLE_FILE_INFORMATION`);
* Migrated version API to **ver2go** 0.2+; CI matrix and lint job;

* added **Version()** (replacing the **Version** constant), formed by **ver2go.CombineVersion()**;
* documented **VersionString()**;
* **VersionAB** now uses **ver2go.Release**;
* updated **ver2go** to 0.2.0-beta1;
* updated **examples/libver.go** to use **VersionString()**;
* version string updated for the 0.0.1 release;

## 0.0.2 - 2nd September 2026

## 0.0.0.5 - 20th August 2026

* CI modernisation (matrix + lint);
* CI reliability fixes (macOS test linking; golangci-lint config verification disabled in CI);
* boilerplate additions (scripts, markdown docs, project identity);
* removed retired Go Report Card badge from README;
* version string updated for the 0.0.0.5 release;
* Version API migrated toward **ver2go** 0.2 facilities;
* Boilerplate / helper-script updates;


## 0.0.0.4 - 18th August 2025
Expand Down
10 changes: 7 additions & 3 deletions EXAMPLES.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
# recls.Go - Examples <!-- omit in toc -->


| Name | Source & Description | Summary |
| ---------- | ---------------------------------------- | -------------------------------------------------------- |
| **libver** | [examples/libver.go](./examples/libver.go)<br/>[examples/libver.md](./examples/libver.md) | Displays the **recls.Go** library version and terminates |
| Name | Source & Description | Details |
| ----------------- | ---------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------- |
| **hard_links** | [examples/hard_links/main.go](./examples/hard_links/main.go)<br/>[examples/hard_links.md](./examples/hard_links.md) | Entries with hard-link count &gt; 1 |
| **libver** | [examples/libver/main.go](./examples/libver/main.go)<br/>[examples/libver.md](./examples/libver.md) | Prints the **recls.Go** version string and those of the dependency libraries |
| **rls** | [examples/rls/main.go](./examples/rls/main.go)<br/>[examples/rls.md](./examples/rls.md) | Listing tool inspired by Synesis **rls** (Ruby) |
| **search_simple** | [examples/search_simple/main.go](./examples/search_simple/main.go)<br/>[examples/search_simple.md](./examples/search_simple.md) | Recursive file search with an optional pattern |
| **stat** | [examples/stat/main.go](./examples/stat/main.go)<br/>[examples/stat.md](./examples/stat.md) | `Stat` on a file or directory path |


<!-- ########################### end of file ########################### -->
13 changes: 7 additions & 6 deletions NEWS.md
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
# recls.Go - News <!-- omit in toc -->


| Date | News Item |
| ---------------- | --------------------------------------------------------------------------------------------------- |
| 20th August 2026 | Release of [**recls.Go** 0.0.1](https://github.com/synesissoftware/recls.Go/releases/tag/0.0.1) |
| 20th August 2026 | Release of [**recls.Go** 0.0.0.5](https://github.com/synesissoftware/recls.Go/releases/tag/0.0.0.5) |
| 18th August 2025 | Release of [**recls.Go** 0.0.0.4](https://github.com/synesissoftware/recls.Go/releases/tag/0.0.0.4) |
| 13th August 2025 | Release of **recls.Go** 0.0.0.3 |
| Date | News Item | Details |
| ------------------ | ------------------------------------------------------------------------------------------------- | ------- |
| 3rd September 2026 | [**recls.Go** 0.1.0-alpha1](https://github.com/synesissoftware/recls.Go) released | First functional alpha (Search + Stat; `PatternSource`) |
| 20th August 2026 | [**recls.Go** 0.0.1](https://github.com/synesissoftware/recls.Go/releases/tag/0.0.1) released | |
| 20th August 2026 | [**recls.Go** 0.0.0.5](https://github.com/synesissoftware/recls.Go/releases/tag/0.0.0.5) released | |
| 18th August 2025 | [**recls.Go** 0.0.0.4](https://github.com/synesissoftware/recls.Go/releases/tag/0.0.0.4) released | |
| 13th August 2025 | **recls.Go** 0.0.0.3 released | |


<!-- ########################### end of file ########################### -->
113 changes: 94 additions & 19 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,59 +2,135 @@

The platform-independent file-system recursive search library, for Go.

![Language](https://img.shields.io/badge/Go-00ADD8?style=flat&logo=go&logoColor=white)

[![Language](https://img.shields.io/badge/Language-Go-blue)](https://go.dev/)
[![License](https://img.shields.io/badge/License-BSD_3--Clause-blue.svg)](https://opensource.org/licenses/BSD-3-Clause)
[![GitHub release](https://img.shields.io/github/v/release/synesissoftware/recls.Go.svg)](https://github.com/synesissoftware/recls.Go/releases/latest)
[![Last Commit](https://img.shields.io/github/last-commit/synesissoftware/recls.Go)](https://github.com/synesissoftware/recls.Go/commits/master)
[![Go](https://github.com/synesissoftware/recls.Go/actions/workflows/go.yml/badge.svg)](https://github.com/synesissoftware/recls.Go/actions/workflows/go.yml)
[![Go Reference](https://pkg.go.dev/badge/github.com/synesissoftware/recls.Go.svg)](https://pkg.go.dev/github.com/synesissoftware/recls.Go)


## Table of contents <!-- omit in toc -->
## Table of Contents <!-- omit in toc -->

- [Introduction](#introduction)
- [Installation](#installation)
- [Components](#components)
- [Entry](#entry)
- [Stat](#stat)
- [Search](#search)
- [Flags](#flags)
- [Examples](#examples)
- [Project Information](#project-information)
- [Where to get help](#where-to-get-help)
- [Contribution guidelines](#contribution-guidelines)
- [Dependencies](#dependencies)
- [Development/Example/Testing Dependencies](#developmentexampletesting-dependencies)
- [Related projects](#related-projects)
- [License](#license)

- [Where to get help](#where-to-get-help)
- [Contribution guidelines](#contribution-guidelines)
- [Dependencies](#dependencies)
- [Development / Testing Dependencies](#development--testing-dependencies)
- [Related projects](#related-projects)
- [License](#license)


## Introduction

**recls** - **rec**ursive **ls** - is a platform-independent recursive file-system search library implemented in C and C++ with a C-API, and a C++ binding. It implemented in several languages: **recls.Go** is the **Go** implementation.
**recls** — **rec**ursive **ls** — is a platform-independent recursive
file-system search library. **recls.Go** is the Go implementation, shaped
around the recls2 architecture:

**recls** is completely free and includes source released under a BSD-style license.
* **libpath.Go** — path decomposition (`PathDescriptor`) for Entry fields;
* **stdlib** (`os`, `io/fs`) — directory traversal and metadata;
* **shwild.Go** — shell-compatible pattern matching (not `filepath.Match`).

**recls** is free software released under a BSD-style license.


## Installation

```Go
```go
import recls "github.com/synesissoftware/recls.Go"
```


## Components


### Entry

`Entry` embeds **libpath** `PathDescriptor` for path decomposition, adds
search-relative fields, and implements `fs.FileInfo`. Nature predicates are
methods (`Exists()`, `IsDir()`, `IsFile()`, `IsLink()`, `IsHidden()`,
`IsReadonly()`); use `Path()` for the recls name of `FullPath`.


### Stat

```go
e, err := recls.Stat(path, recls.DirectoryParts|recls.MarkDirs)
```

`DetailsLater` allows a path-only entry when the path does not exist.


### Search

Depth-first recursive search. Patterns are matched against the **entry
basename** via **shwild**. `patterns` is a **`PatternSource`**: either a
multi-pattern string (split on `|` or the platform path-list separator —
`:` on Unix, `;` on Windows) or a `[]string` of discrete patterns (not
re-split).

```go
opts := recls.SearchOptions{Flags: recls.Files | recls.Recursive}
for e, err := range recls.Search(root, "*.go", opts) {
if err != nil { /* ... */ }
fmt.Println(e.SearchRelativePath)
}
```

Or callback style, with a string or a slice:

```go
err := recls.SearchFunc(root, "*.go|*.md", opts, func(e recls.Entry) error {
fmt.Println(e.Path())
return nil
})

err = recls.SearchFunc(root, []string{"*.go", "*.md"}, opts, func(e recls.Entry) error {
fmt.Println(e.Path())
return nil
})
```


### Flags

Core flags (aligned with C `RECLS_F_*`): `Files` (default type),
`Directories`, `Links`, `Recursive`, `DirectoryParts`, `MarkDirs`,
`IgnoreHiddenEntries`, `StopOnAccessFailure`, `NoFollowLinks`,
`NoBreakInfiniteLoops`, `DirProgress`, `UseTildeOnNoSearchRoot`,
`DetailsLater`.

Explicitly out of scope for v0.1 (see **TODO.md**): FTP, devices, sockets,
BFS, `RemoveDirectory`, checksums, Windows reparse-dir edge cases.


## Examples

Examples are provided in the ```examples``` directory, along with a markdown description for each. A detailed list TOC of them is provided in [EXAMPLES.md](./EXAMPLES.md).
Examples are provided in the `examples` directory, along with a markdown
description for each. A detailed TOC is in [EXAMPLES.md](./EXAMPLES.md).


## Project Information


### Where to get help

[GitHub Page](https://github.com/synesissoftware/recls.Go "GitHub Page")
[GitHub Page](https://github.com/synesissoftware/recls.Go)


### Contribution guidelines

Defect reports, feature requests, and pull requests are welcome on https://github.com/synesissoftware/recls.Go.
Defect reports, feature requests, and pull requests are welcome on
https://github.com/synesissoftware/recls.Go.


### Dependencies
Expand All @@ -64,10 +140,8 @@ Defect reports, feature requests, and pull requests are welcome on https://githu
* [**ver2go**](https://github.com/synesissoftware/ver2go/);


#### Development/Example/Testing Dependencies
#### Development / Testing Dependencies

* [**CLASP.Go**](https://github.com/synesissoftware/CLASP.Go/);
* [**STEGoL**](https://github.com/synesissoftware/STEGoL/);
* [**testify**](https://github.com/stretchr/testify);


Expand All @@ -81,7 +155,8 @@ Defect reports, feature requests, and pull requests are welcome on https://githu

### License

**recls.Go** is released under the 3-clause BSD license. See [LICENSE](./LICENSE) for details.
**recls.Go** is released under the 3-clause BSD license. See [LICENSE](./LICENSE)
for details.


<!-- ########################### end of file ########################### -->
25 changes: 21 additions & 4 deletions TODO.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,18 +10,35 @@

## Functional improvements

* \<none>
* [ ] BFS search order (recls.NET-style);
* [ ] `RemoveDirectory` helper;
* [ ] Devices / sockets type filters;
* [x] ~~~Link count metadata~~~ - ✅ (`Entry.LinkCount`);
* [ ] Node index metadata;
* [ ] FTP search (`RECLS_F_PASSIVE_FTP`);
* [ ] CalcChecksum;
* [ ] Windows `AllowReparseDirs` edge cases;
* [ ] Windows flag so leading-dot names are not treated as hidden (apply in `ProbeHidden` / `IsHiddenName`; Unix-style `.name` convention becomes optional on Windows);
* [ ] Windows file attributes (system, archive, compressed, …) via a Windows-only interface (`//go:build windows`); wire into **rls** example attribute letters (S/T/V/A/E/C per Ruby **rls**);
* [ ] Public path helpers (`CombinePaths`, `DeriveRelativePath`, `CanonicalisePath`) — currently internal / stdlib;
* [ ] Upstream `derive_relative_path` / trailing-separator helpers into **libpath.Go** (recls currently carries thin internal copies);
* [ ] Upstream path compare / case-fold helpers into **libpath.Go** (Ruby has `make_compare_path`; use for Windows-aware `pathElementsEqual`);
* [ ] `DirProgress` example and richer progress API;
* [ ] Consider **recls.NET**-style callbacks to filter / decide fate of inaccessible directories (beyond binary StopOnAccessFailure vs skip);
* [x] ~~~Consider generics so `patterns` may be a `string` or an array of strings~~~ - ✅ (`PatternSource`);


## Performance improvements

* \<none>
* [ ] Consider caching compiled patterns across multi-root searches;
* [ ] Optimise patterns: if a wildcards-all (`*`) is present, elide all other patterns;
* [ ] Optional read-ahead / buffered directory reads for large trees;


## Packaging improvements

* [ ] Before the next official release: confirm **`go.mod`** (`go 1.21`) and the CI Go-version matrix, bump Synesis `require`s to newly published tags, then run **`go mod tidy`** (not against currently published tags). Prior Synesis Go releases, in order:
* **ver2go**;
* [ ] Align **NEWS.md** Details column with umbrella packaging programme;
* [x] ~~~Drop local `replace` directives once published dependency versions cover CI~~~ - ✅;


<!-- ########################### end of file ########################### -->
23 changes: 23 additions & 0 deletions constants_unix.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
// Copyright 2019-2026, Matthew Wilson and Synesis Information Systems. All
// rights reserved. Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

//go:build unix

/*
* Created: 3rd September 2026
* Updated: 3rd September 2026
*/

package recls

import (
libpath_unix "github.com/synesissoftware/libpath.Go/util/unix"
)

const (
// Platform path-name (directory) separator.
PathNameSeparator = string(libpath_unix.PathElementSeparator)
// Platform path-list separator (e.g. for multi-pattern search strings).
PathSeparator = string(libpath_unix.PathSeparator)
)
23 changes: 23 additions & 0 deletions constants_windows.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
// Copyright 2019-2026, Matthew Wilson and Synesis Information Systems. All
// rights reserved. Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

//go:build windows

/*
* Created: 3rd September 2026
* Updated: 3rd September 2026
*/

package recls

import (
libpath_windows "github.com/synesissoftware/libpath.Go/util/windows"
)

const (
// Platform path-name (directory) separator.
PathNameSeparator = string(libpath_windows.PathElementSeparator)
// Platform path-list separator (e.g. for multi-pattern search strings).
PathSeparator = string(libpath_windows.PathSeparator)
)
Loading
Loading