A cross-platform, managed implementation of the GNU Coreutils/Fileutils/Textutils command family for .NET 10, written in C# 13.
Icod.CoreUtils brings familiar Unix command-line utilities to Windows, Linux, and macOS while preserving GNU-compatible command syntax and behavior wherever the underlying operating system permits it. The implementation is managed C# rather than a wrapper around installed GNU executables: ordinary command behavior is implemented by the repository itself.
The current suite contains 105 command projects, available both as individual executables and through the coreutils multicall router.
Important
Icod.CoreUtils is an independent implementation and is not an official GNU or Free Software Foundation project. GNU Coreutils is used as the primary behavioral and command-line compatibility reference.
Icod.CoreUtils stands on a long tradition of Unix command-line software. It is inspired by the original UNIX utilities and by decades of design, implementation, maintenance, documentation, and testing performed by the many authors, maintainers, and contributors responsible for GNU fileutils, textutils, shellutils, and GNU Coreutils. Their work provides the historical and behavioral foundation against which this independent managed implementation is designed and audited.
The original UNIX systems and utilities, GNU Coreutils and its predecessor projects, and their respective source code and copyrights remain the work of their respective authors and copyright holders.
C#/.NET migration and Icod.CoreUtils implementation: Timothy J. Bruce uniblab@hotmail.com
Copyright (C) 2026 Timothy J. Bruce uniblab@hotmail.com.
This attribution is intended to recognize the work on which Icod.CoreUtils is based and inspired while distinguishing that prior work from the independent C#/.NET implementation in this repository.
The project aims to provide:
- familiar GNU Coreutils behavior, option syntax, diagnostics, output formats, and exit-status conventions;
- one maintained C# implementation that can run across Windows, Linux, and macOS;
- explicit handling of differences between POSIX and Windows filesystems, processes, terminals, security models, and path grammars;
- managed implementations of command behavior rather than delegating ordinary work to an installed host utility;
- reusable, independently testable command engines separated from their executable process hosts;
- deterministic and testable abstractions for paths, filesystems, terminal behavior, process interaction, cancellation, and standard streams;
- controlled diagnostics for genuinely unsupported operating-system facilities rather than silently pretending that another platform provides Unix capabilities it does not have;
- both traditional standalone command executables and a convenient single
coreutils.NET tool router.
Compatibility is an ongoing engineering target rather than a claim that every operating system exposes identical facilities. Commands whose semantics depend on SELinux, POSIX ownership, special files, terminal descriptors, privilege boundaries, or other platform-specific facilities may necessarily differ in availability while retaining controlled and documented behavior.
The coreutils router currently includes 105 command projects:
Show all 105 commands
arch, b2sum, base32, base64, basename, basenc, cat, chcon, chgrp, chmod, chown, chroot, cksum, comm, cp, csplit, cut, date, dd, df, dir, dircolors, dirname, du, echo, env, expand, expr, factor, false, fmt, fold, groups, head, hostid, hostname, id, install, join, link, ln, logname, ls, md5sum, mkdir, mkfifo, mknod, mktemp, mv, nice, nl, nohup, nproc, numfmt, od, paste, pathchk, pinky, pr, printenv, printf, ptx, pwd, readlink, realpath, rm, rmdir, runcon, seq, sha1sum, sha224sum, sha256sum, sha384sum, sha512sum, shred, shuf, sleep, sort, split, stat, stdbuf, stty, sum, sync, tac, tail, tee, test, timeout, touch, tr, true, truncate, tsort, tty, uname, unexpand, uniq, unlink, users, vdir, wc, who, whoami, yes
Each command remains a standalone executable project. The router simply provides an additional composition layer:
coreutils COMMAND [OPTION]... [ARG]...
For example:
coreutils ls -la
coreutils sha256sum README.md
coreutils sort input.txt
coreutils cp source.txt destination.txt
Run:
coreutils COMMAND --help
for the selected utility's command-specific help.
The authoritative upstream baseline for the current CoreUtils command family is GNU Coreutils 9.11.
The repository maintains an explicit, non-floating upstream-version ledger. Completed behavior does not silently change merely because a newer upstream package becomes available. Deliberate compatibility rebases are recorded and reviewed.
Important specification authorities include:
| Authority | Baseline | Purpose |
|---|---|---|
| GNU Coreutils | 9.11 | Primary Coreutils command behavior |
| GNU Gnulib | Coreutils 9.11 pinned revision | Shared GNU semantics used by applicable commands |
| POSIX | POSIX.1-2024 / Issue 8 | Standardized Unix utility and system behavior |
net-tools hostname |
2.10 | Traditional Linux hostname compatibility profile |
The repository's hostname command intentionally follows the traditional Linux net-tools interface rather than treating that command as part of the GNU Coreutils specification.
See Icod.CoreUtils-Upstream-Version-Ledger.md for the authoritative per-command and per-batch specification pins.
The primary supported CI hosts are:
| Platform | CI | Release architecture |
|---|---|---|
| Windows | windows-latest |
x64, ARM64 |
| Linux | ubuntu-latest |
x64, ARM64 |
| macOS | macos-latest |
x64, ARM64 |
BSD portability is a best-effort project goal, but BSD is not currently part of the required CI matrix.
Platform support does not mean that every operating system exposes identical semantics. Commands requiring facilities that do not exist on the active host must report that limitation in a controlled manner rather than fabricate success.
To build the repository:
- .NET 10 SDK
- a Git client
- Windows, Linux, or macOS
The projects target:
net10.0
and use:
C# 13
Release archives are framework-dependent and require the .NET 10 runtime on the target machine.
The simplest way to run a command from the source tree is through the router:
dotnet run --project coreutils/Icod.CoreUtils.Router.csproj -- ls -la
or:
dotnet run --project coreutils/Icod.CoreUtils.Router.csproj -- sha256sum README.md
Every retained command also has its own executable project:
dotnet run --project cat/Icod.CoreUtils.Cat.csproj -- README.md
dotnet run --project ls/Icod.CoreUtils.Ls.csproj -- -la
dotnet run --project sha256sum/Icod.CoreUtils.Sha256Sum.csproj -- README.md
This standalone-project structure is intentional. The router is a convenience layer; it is not the implementation of the commands themselves.
coreutils/Icod.CoreUtils.Router.csproj is configured as a .NET tool package with:
PackageId: Icod.CoreUtils
ToolCommandName: coreutils
From a package source containing the package, install it with:
dotnet tool install --global Icod.CoreUtils
Then invoke commands through:
coreutils ls -la
coreutils cat file.txt
coreutils sha256sum file.bin
A locally packed package can likewise be installed from the repository's artifacts directory by adding that directory as a package source.
The repository includes equivalent build entry points for Windows and Unix-like hosts.
build.cmd
./build.sh
With no argument, the scripts perform the complete local pipeline:
clean
restore
build
test
pack
validate
An individual stage can also be selected:
build.cmd test
build.cmd pack
or:
./build.sh test
./build.sh pack
The default script pipeline uses the Debug configuration and writes package artifacts to:
artifacts/
The equivalent basic commands are:
dotnet clean Icod.CoreUtils.sln -c Debug
dotnet restore Icod.CoreUtils.sln
dotnet build Icod.CoreUtils.sln -c Debug --no-restore
dotnet test Icod.CoreUtils.sln -c Debug --no-build
Before release-oriented work, validate the Release configuration as well:
dotnet clean Icod.CoreUtils.sln -c Release
dotnet restore Icod.CoreUtils.sln
dotnet build Icod.CoreUtils.sln -c Release --no-restore
dotnet test Icod.CoreUtils.sln -c Release --no-build
The repository defines three build configurations:
Debug
Staging
Release
Release builds use the repository's stricter warning policy and treat compiler warnings as errors except for the currently exempted CS1591 documentation warning.
Pull requests are validated in the Staging configuration on:
windows-latest
ubuntu-latest
macos-latest
Pushes to main are validated in the Release configuration on the same three operating-system families.
The release workflow is separately triggered by SemVer-style v* tags. Release tags must identify commits contained in main, and the tag version must agree with both <Version> and <PackageVersion> in the coreutils router project.
Release validation covers:
Windows x64
Windows ARM64
Linux x64
Linux ARM64
macOS x64
macOS ARM64
The project supports two complementary distribution styles.
The Icod.CoreUtils .NET tool package installs one coreutils command which dispatches directly to the corresponding managed command implementation:
coreutils COMMAND [OPTION]... [ARG]...
The selected command retains ownership of its parsing, pathname interpretation, diagnostics, command semantics, and exit status.
The release pipeline is also designed to produce platform-specific archives containing the traditional individual command executables together with the coreutils router.
This allows users to choose between:
coreutils ls -la
and the traditional form:
ls -la
without maintaining separate command implementations.
Icod.CoreUtils is no longer the large incubation repository in which several neighboring Unix command suites once lived.
Completion Gate G is complete.
The repository now owns the GNU Coreutils/Fileutils/Textutils command family and its repository-local support code. Other command families and reusable mechanisms have been moved behind explicit repository and package boundaries.
The normal dependency direction is:
published neutral package
↓
Icod.CoreUtils.Shared
↓
individual command project
↓
Program.cs executable composition root
Not every command requires every layer.
Program.cs owns attachment to the current operating-system process: arguments, standard streams, Ctrl+C or signal integration, and other process-global resources.
The command implementation owns command semantics: parsing, diagnostics, execution policy, output behavior, and exit status.
This separation allows command engines to be called directly by tests and other managed code without pretending that every invocation necessarily originates from a console process.
Shared/Icod.CoreUtils.Shared.csproj contains behavior genuinely shared by the Coreutils command family.
It is intentionally:
repository-local
non-packable
It must not become an accidental cross-repository dependency.
Cross-suite mechanism belongs in neutral packages such as Icod.CommandFramework, Icod.Path, Icod.Terminal, and the other Icod foundation libraries.
Several command families were originally developed inside this repository while the broader Unix-tool migration was being bootstrapped. They now have authoritative homes of their own:
| Suite | Repository | Examples |
|---|---|---|
| Grep | Icod.Grep | grep |
| Diffutils | Icod.DiffUtils | cmp, diff, diff3, sdiff |
| Tar | Icod.Tar | tar |
| ProcPs | Icod.ProcPs | procps-ng command family |
| Patch | Icod.Patch | patch |
| Line Editor | Icod.LineEditor | ed, red, sed |
| UtilLinux | Icod.UtilLinux | util-linux command family |
These suites must not be reintroduced into Icod.CoreUtils merely to share implementation code. Cross-repository reuse belongs behind a published neutral package or a public interoperability format.
For the full architecture record, see Icod.CoreUtils-Architecture-and-Migration.md.
At a high level:
Icod.CoreUtils/
├── coreutils/ multicall router / .NET tool package
├── Shared/ repository-local Coreutils shared library
├── arch/ individual command project
├── cat/
├── cp/
├── ls/
├── ...
├── tests/ command and shared-library test projects
├── packaging/ distribution support
├── .github/ CI, release, and repository automation
├── Icod.CoreUtils.sln
├── build.cmd
├── build.sh
├── CONTRIBUTING.md
├── LICENSE
└── README.md
Each command directory normally contains its executable project, Program.cs, command implementation sources, and command-specific documentation.
Icod.CoreUtils provides consistent in-process pathname globbing for appropriate filesystem operands through Icod.CommandFramework, rather than relying exclusively on the invoking shell to expand pathnames. This gives Class A and Class B utilities a defined cross-platform expansion model when wildcard-bearing operands reach the application unexpanded.
Globbing is command- and operand-specific. A utility must expand only operands whose semantic role is an eligible filesystem pathname. It must not blindly expand every argument merely because the argument contains wildcard characters. Destination names, names being created, lexical pathname text, expressions, data, and arguments belonging to a child command remain literal unless a tool explicitly defines otherwise.
For this CoreUtils policy, the pathname glob syntax is:
*— matches zero or more characters within one pathname component; it does not consume a pathname separator.?— matches exactly one character within one pathname component; it does not consume a pathname separator.**— matches zero or more complete pathname components when, and only when, the complete component is exactly**. For example,src/**/*.csis recursive, while an occurrence of**embedded inside another component does not acquire recursive meaning.
Recursive ** expansion is pathname selection. It does not imply or enable a utility's own recursive operation. For example, expanding rm **/*.tmp produces explicit operands; it does not grant rm permission to recursively remove directories. Likewise, expanding a set of pathnames for chmod is distinct from chmod -R. Wildcards do not match a leading . unless the pattern names that period explicitly. Matching is ordinal case-insensitive on Windows and ordinal case-sensitive on other supported hosts.
Class A expansion preserves operand order and repetition. Explicitly named intermediate symbolic-link components may be followed where necessary to reach the named path, while wildcard-discovered symbolic-link directories are not recursively traversed by globbing. Globbing selects pathnames; it does not canonicalize literal operands.
The invoking shell may already have expanded an unquoted pattern before the utility starts. In that case the utility simply receives the resulting literal pathname operands. The policy in this section governs wildcard-bearing pathname operands that reach an Icod.CoreUtils application unexpanded.
For the Class A utilities below, an unmatched pattern is preserved as its original literal operand. Commands then apply their ordinary operand semantics to that literal. The conventional - operand is likewise preserved for commands that use it as a standard-input or standard-output sentinel.
The following utilities implement the repository pathname-globbing policy for their eligible command-line pathname operands.
| Area | Utilities |
|---|---|
| File content and input | cat, cut, expand, fmt, fold, head, nl, od, paste, pr, sort, tac, tail, unexpand, wc |
| Checksums and hashes | b2sum, cksum, md5sum, sha1sum, sha224sum, sha256sum, sha384sum, sha512sum, sum |
| File inspection and reporting | df, dir, du, ls, readlink, realpath, stat, vdir |
| Copy, move, and install | cp, install, mv |
| Metadata mutation | chcon, chgrp, chmod, chown |
| Removal and destructive operations | rm, rmdir, shred |
| Other pathname operations | sync, touch, truncate |
Eligibility remains operand-specific even for utilities in this table. In particular, source collections may be expandable while destinations and other singular control operands remain literal. The following qualifications are part of the Class A contract:
cp,mv, and ordinary file-copy forms ofinstallexpand source operands only. Destination operands and--target-directoryvalues remain literal.install -ddirectory-creation operands remain literal because they name objects to be created.- Option values such as
--reference=FILEremain literal unless a command explicitly documents otherwise. Owner/group/mode/context specifications are not pathname patterns. sort --files0-from,wc --files0-from, anddu --files0-fromtreat names read from those lists literally; command-line pathname operands remain independently eligible for expansion.readlinkandrealpathpreserve the original spelling of non-pattern operands so thatIcod.Pathcan interpret the intended pathname dialect.realpath --relative-toand--relative-basevalues remain literal.**selects explicit operands only. Command recursion such asls -R,chmod -R, ownership recursion,rm -r,rmdir --parents, anddutraversal remains controlled by each utility's own options and semantics.- Old-style
odoffset/label operands are classified before pathname expansion, so only actual file operands are globbed.
Class B uses the same pathname syntax, leading-dot rule, platform case behavior, symbolic-link traversal policy, and literal-preservation rules as Class A, but it preserves the command's syntactic arity. A singular pathname slot is expanded independently: a literal operand remains literal, an unmatched pattern remains literal, exactly one match replaces the pattern, and more than one match is an error. Matches from one singular slot never spill into another argument position.
Some Class B commands are mode-aware. An argument position is eligible only when the command grammar has already identified it as an existing-path input. Data operands, destinations, names being created, symbolic-link payload text, and option values remain literal unless a command explicitly documents otherwise.
| Area | Utilities |
|---|---|
| Encoded-data input | base32, base64, basenc |
| Fixed-arity file comparison | comm, join |
| Splitting, filtering, indexing, and ordering | csplit, split, uniq, ptx, shuf, tsort |
| Link and name operations | ln, link, unlink |
| Configuration and accounting input | dircolors, users, who |
The following qualifications are part of the Class B contract:
base32,base64,basenc, andtsortsingular-expand their optional inputFILE;-remains standard input.commandjoinexpandFILE1andFILE2independently. Each slot may resolve to exactly one pathname, but expansion never flattens the two slots into a shared operand list.csplitexpands only its initial inputFILE; every followingPATTERNremains command-language syntax.splitexpands only its inputFILE; outputPREFIXremains literal.uniqlikewise expands onlyINPUT;OUTPUTremains literal.ptxuses collection expansion for GNU-extension input operands. Traditional[INPUT [OUTPUT]]mode singular-expandsINPUTand leavesOUTPUTliteral. Break/ignore/only parameter-file option values remain literal.shufsingular-expands its positionalFILEonly in ordinary file mode.--echooperands are data,--input-rangehas no pathname operand, and--outputand--random-sourcevalues remain literal.lnnever expands symbolic-link targets. Hard-link sources use collection expansion only when the already-selected grammar targets a directory; otherwise the source is a singular slot. Destination names and target-directory operands remain literal.linksingular-expands existing sourceFILE1while creation nameFILE2remains literal.unlinksingular-expands its one pathname and rejects multiple matches before attempting removal.dircolorsanduserssingular-expand their optional inputFILE.whosingular-expands only the one-operand accounting-file form; the traditional two-operand form remains literal control syntax.
Class C utilities will not perform Icod.CommandFramework pathname expansion. This does not prevent an invoking shell from expanding a pattern before launching the utility; it means the utility itself will not reinterpret wildcard-bearing arguments as filesystem glob patterns.
| Area | Utilities |
|---|---|
| Host, process, environment, and identity information | arch, groups, hostid, hostname, id, logname, nproc, pinky, printenv, pwd, tty, uname, whoami |
| Numeric, data, and string operations | echo, expr, factor, numfmt, printf, seq, sleep, tr, yes |
| Pure status commands | false, true |
| Creation and template commands | mkdir, mkfifo, mknod, mktemp |
| Lexical and destination pathname grammars | basename, dirname, pathchk, tee |
| Singular control and option-file grammars | chroot, date, stty |
| Command wrappers and executors | env, nice, nohup, runcon, stdbuf, timeout |
| Special command grammars | dd, test |
| Multicall dispatcher | coreutils |
This exclusion is intentional. Creation-oriented utilities must preserve the names they are asked to create. Data- and expression-oriented utilities may legitimately receive *, ?, or ** as ordinary text. basename and dirname operate lexically on supplied pathname-shaped strings, while pathchk examines the pathname spelling itself. tee operands are output destinations. chroot keeps its process-root boundary explicit, and the path-valued arguments accepted by date and stty are option/control values rather than general input pathname operands. Wrapper utilities must pass the child command and its arguments through without reinterpreting them. dd and test have command grammars in which automatic argv expansion would alter the meaning of the command. The coreutils multicall dispatcher likewise leaves pathname policy to the selected utility rather than applying globbing itself.
The Class A, Class B, and Class C tables above define the pathname-expansion policy for the current command suite. New utilities or new operand forms must choose their pathname class explicitly rather than inheriting globbing merely because an argument happens to contain wildcard characters.
The root of the repository contains the durable engineering records used during the compatibility, audit, and repository-migration work.
The most useful entry points are:
- Icod.CoreUtils-Audit-and-Refactor-Roadmap.md — detailed implementation, audit, and completion roadmap.
- Icod.CoreUtils-Upstream-Version-Ledger.md — authoritative upstream specification pins.
- Icod.CoreUtils-Architecture-and-Migration.md — final repository/package ownership and architecture after Completion Gate G.
- Completion-Gate-G_Repository-Migration-Checklist-and-Roadmap.md — migration and extraction record.
- Icod.CoreUtils-G10B-Dependency-Audit.md — cross-repository dependency and isolation audit.
- CONTRIBUTING.md — contribution, implementation, testing, and style requirements.
The roadmaps deliberately distinguish implemented behavior, local validation, three-runner CI validation, platform-limited behavior, and deliberately deferred work.
Contributions are welcome.
Before making a substantive change, please read CONTRIBUTING.md.
In particular:
- preserve GNU-compatible behavior unless an intentional divergence is documented;
- add focused automated tests for behavioral changes;
- preserve the command/
Program.cscomposition-root boundary; - do not introduce source-tree dependencies on neighboring Icod repositories;
- do not delegate ordinary command behavior to the host GNU or Unix executable;
- use the repository's shared path, filesystem, command, process, and terminal abstractions rather than creating command-local substitutes;
- validate the complete solution before submitting a pull request;
- keep platform limitations explicit and controlled.
The repository-level distribution and coreutils router are licensed under the GNU General Public License, version 3 or later.
See LICENSE for the full license text and consult individual project/file notices where additional licensing information applies.
The managed implementation is copyright © 2026 Timothy J. Bruce and contributors.
GNU, GNU Coreutils, GNU Gnulib, POSIX, Linux, Windows, macOS, and other names referenced by this project belong to their respective projects and owners. They are referenced for compatibility, interoperability, and specification purposes.
This project exists because of the decades of work represented by GNU Coreutils, GNU Gnulib, POSIX, the Unix tradition, the .NET runtime and libraries, and the maintainers of the operating systems on which these tools run.
The objective of Icod.CoreUtils is not to hide those origins, but to preserve the familiar command-line contracts while making them available through a modern managed, cross-platform implementation.
