# Command Implementation Status
This document tracks the implementation status of commands in the WinuxCmd project, which now uses a pipeline-based architecture for command processing.
## Categories
### File Management
| Command | Status | Priority | Description | Parameters/Options | Implementation Notes |
|---------|--------|----------|-------------|-------------------|---------------------|
| `ls` | ✅ Done | High | List directory contents | `-a, --all`: Do not ignore entries starting with `.`
`-A, --almost-all`: Do not list implied `.` and `..`
`-b, --escape`: Print C-style escapes for nongraphic characters
`-d, --directory`: List directories themselves, not their contents
`-f`: List all entries in directory order
`-F, --classify`: Append indicator characters to entries
`--file-type`: Append type indicators but not `*` for executables
`-I, --ignore=PATTERN`: Ignore entries matching PATTERN
`--hide=PATTERN`: Hide entries matching PATTERN unless `-a` or `-A` is active
`-l, --long, --long-list`: Use a long listing format
`--full-time`: Equivalent to `-l --time-style=full-iso`
`--author`: Show an author column in long format
`-h, --human-readable`: With `-l`, print sizes in human readable format
`-r, --reverse`: Reverse order while sorting
`-t`: Sort by modification time
`-U`: Do not sort; list entries in directory order
`-v`: Natural sort of version-like numbers
`-X, --sort=WORD`: Sort by a selected key such as `extension`
`-n, --numeric-uid-gid`: Like `-l`, but list numeric user and group IDs
`-g`: Like `-l`, but do not list owner
`-o`: Like `-l`, but do not list group information
`-1`: List one file per line
`-C`: List entries by columns
`-w, --width`: Set output width to COLS
`--indicator-style=WORD`: Select slash/file-type/classify/none suffixes
`--color`: Colorize output | Implemented with pipeline architecture, supports color output, SmallVector optimization, now preserves GNU-style directory headers for surviving directory/junction operands when sibling operands fail, routes missing-path `cannot access` diagnostics to stderr with GNU-style exit status `2`, keeps `-F/--classify/--file-type` indicators on the symlink/junction name itself rather than on the displayed target, reports Windows directory junction sizes as `0` in long format instead of reusing the rendered target-path length, trims raw Windows namespace prefixes such as `\??\` / `\\?\` from displayed junction targets, accepts command-line directory/junction operands with trailing separators such as `dir/` or `junc/` while preserving the original operand spelling, in long colorized output now colors the link name and displayed target separately instead of painting the whole `name -> target` span as one link-colored block, now accepts GNU `--long` as a direct alias of `-l`, now accepts both singular and plural `--dereference-command-line-symlink(s)-to-dir` long forms, now accepts GNU `--full-time` as `-l --time-style=full-iso` while still letting later format/time-style options override it, now treats GNU `-g`, `-n`, and `-o` as long-format requests like `-l` while still letting later explicit format options override them, now also suppresses the corresponding owner/group columns for GNU `-g`, `-o`, and `--no-group`, `--hide=PATTERN` now matches GNU/Microsoft behavior by hiding matching names only in default mode while `-a` / `-A` override it and `--ignore=PATTERN` still filters even in all-mode listings, GNU `--author` is now accepted and emits an extra long-format author column using the same Windows owner approximation as Microsoft/Coreutils, now mirrors Microsoft Coreutils' Windows permission approximation by showing writable entries as `rwxrwxrwx` and read-only ones as `r-xr-xr-x`, now re-probes real directory metadata for long-format `.` / `..` entries so parent-directory size and `total` no longer collapse to synthetic zeroes, now also keeps the synthetic `.` entry on the dereferenced target-directory view for `ls -laL DIRLINK` style directory-symlink or junction listings, now keeps default `-s` output plus directory `total` lines on the closer Windows/Coreutils allocated-byte convention instead of pre-dividing by 1K blocks, and on Windows `--block-size=SIZE` / `-k` now rescale only the long-format size column while `-s` plus directory `total` stay on that byte-based view unless `-h` or `--si` is selected; C/shell/escape quoting now also applies to the displayed symlink target in long format too instead of leaving the target path raw |
| `cat` | ✅ Done | High | Concatenate files and print on the standard output | `-A, --show-all`: Equivalent to `-vET`
`-b, --number-nonblank`: Number only non-empty output lines
`-e`: Equivalent to `-vE`
`-E, --show-ends`: Display $ at end of each line
`-n, --number`: Number all output lines
`-s, --squeeze-blank`: Squeeze multiple adjacent empty lines
`-t`: Equivalent to `-vT`
`-T, --show-tabs`: Display TAB characters as `^I`
`-u`: GNU compatibility placeholder, currently ignored
`-v, --show-nonprinting`: Show nonprinting characters | Simple file reading and writing with pipeline structure, SmallVector optimization |
| `cp` | ✅ Done | High | Copy files and directories | `-a, --archive`: Recursive copy and preserve Windows timestamps/attributes
`-p`: Preserve Windows timestamps/attributes
`-i, --interactive`: Prompt before overwrite
`-r, -R, --recursive`: Copy directories recursively
`-t, --target-directory`: Copy all SOURCE arguments into DIRECTORY
`-T, --no-target-directory`: Treat DEST as a normal file
`--strip-trailing-slashes`: Strip trailing `/` or `\` from each source operand before lookup
`-n, --no-clobber`: Do not overwrite an existing file
`-u, --update`: Copy only when SOURCE is newer than DEST
`-v, --verbose`: Explain what is being done
`-f, --force`: Force copy without prompt | File system operations with error handling; owner/mode preservation is a Windows approximation, and GNU-style source trailing slash stripping is now supported |
| `mv` | ✅ Done | High | Move (rename) files | `-i, --interactive`: Prompt before overwrite
`-I`: Prompt once before larger batches
`-v, --verbose`: Explain what is being done
`-f, --force`: Do not prompt before overwriting
`-n, --no-clobber`: Do not overwrite an existing file
`--interactive[=WHEN]`: GNU-style overwrite prompt mode with last-option precedence | File system operations with error handling, SmallVector optimization |
| `rm` | ✅ Done | High | Remove files or directories | `-f, --force`: Ignore nonexistent files and arguments, never prompt
`-i, --interactive`: Prompt before every removal
`-r, -R, --recursive`: Remove directories and their contents recursively
`-v, --verbose`: Explain what is being done | File system operations with error handling; missing operands now also print the GNU-style `Try 'rm --help' for more information.` hint |
| `mkdir` | ✅ Done | High | Make directories | `-p, --parents`: No error if existing, make parent directories as needed
`-v, --verbose`: Print a message for each created directory
`-m, --mode`: Set file mode (as in chmod) | File system operations with error handling; missing operands now include the GNU-style help hint |
| `rmdir` | ✅ Done | Medium | Remove empty directories | `--ignore-fail-on-non-empty`: Ignore each failure to remove a directory that is non-empty
`-p, --parents`: Remove DIRECTORY and its ancestors
`-v, --verbose`: Print a message for each removed directory | File system operations with error handling; missing operands now include the GNU-style help hint, file operands now report the more GNU-shaped `Not a directory` diagnostic, `-v` now prints the GNU/uutils-shaped `removing directory, 'DIR'` line before every attempted removal including failures, and `-p` now returns failure if ancestor cleanup stops on a non-empty parent |
| `touch` | ✅ Done | Medium | Change file timestamps or create empty files | `-a`: Change only the access time
`-m`: Change only the modification time
`-c, --no-create`: Do not create any files
`-d, --date`: Parse STRING and use it instead of current time
`-r, --reference`: Use this file's times instead of current time
`-t, --time`: Use the specified timestamp instead of the current time
`-h, --no-dereference`: Change each symbolic link rather than any referenced file
`--time=WORD`: Change the specified time type | File system operations with error handling |
| `basename` | ✅ Done | Low | Strip directory and suffix from file names | `-a, --multiple`: Support multiple arguments and treat each as a NAME
`--mul`: Accepted abbreviation for `--multiple`
`-s, --suffix=SUFFIX`: Remove a trailing SUFFIX and imply multi-name mode even when `SUFFIX` is empty
`--suf`: Accepted abbreviation for `--suffix`
`-z, --zero`: End each output line with NUL
`--ze`: Accepted abbreviation for `--zero`
GNU-shaped operand diagnostics: missing operand help hint and non-`-a` extra operand rejection
Slash-only root inputs such as `/`, `//`, and `///` now normalize to a single root separator
GNU suffix rule: do not strip a suffix that is identical to the entire remaining basename | File name processing |
| `dirname` | ✅ Done | Low | Strip last component from file name | `-z, --zero`: End each output line with NUL
GNU-shaped operand diagnostics: missing operand help hint
Slash-only root inputs such as `/`, `//`, and `///` now normalize to a single root separator
Absolute top-level paths such as `/usr/` keep `/` as the parent directory | File name processing |
| `readlink` | ✅ Done | Low | Print resolved symbolic links or canonical file names | `-f, --canonicalize`: Canonicalize by following every symlink
`-e, --canonicalize-existing`: Canonicalize by following every symlink and verify existence
`-m, --canonicalize-missing`: Canonicalize by following every symlink and verify existence without requirement
`-n, --no-newline`: Do not output the trailing delimiter
`-q, -s, --quiet, --silent`: Suppress most diagnostics
`-v, --verbose`: Report diagnostics
`-z, --zero`: End each output line with NUL
GNU-shaped operand diagnostics: missing operand help hint | Symbolic link resolution; default diagnostics stay quiet, both the canonicalization mode family plus `-q/-s/-v` now follow last-occurrence precedence, and `POSIXLY_CORRECT` now restores GNU-style regular-file diagnostics while ignoring `-q/-s` |
| `realpath` | ✅ Done | Low | Print the resolved absolute path | `-e, --canonicalize-existing`: All components of the path must exist
`-E, --canonicalize`: All but the last path component must exist
`-m, --canonicalize-missing`: No path components need to exist
`-L, --logical`: Accepted; Windows path normalization is used
`-P, --physical`: Accepted; Windows path normalization is used
`-q, --quiet`: Suppress error messages
`-s, --strip, --no-symlinks`: Don't expand symlinks
`--relative-to=DIR`: Print the resolved path relative to DIR
`--relative-base=DIR`: Print relative output only for paths below DIR
`-z, --zero`: End each output line with NUL
GNU-shaped operand diagnostics: missing operand help hint and invalid empty-string rejection | Path resolution; at least one path operand is now required, `-e`, `-E`, and `-m` follow last-occurrence precedence, empty path/relative operands are rejected as invalid empty strings, `-e` now requires `--relative-to` / `--relative-base` to resolve to directories, and full GNU `-L` versus `-P` symlink ordering is still partial |
| `stat` | ✅ Done | Medium | Display file or file system status | `-c, --format=FORMAT`: Use the specified FORMAT instead of the default and append a newline
`--printf=FORMAT`: Like `--format`, but interpret backslash escapes and do not append a newline
`-f, --file-system`: Display file system status instead of file status
`-L, --dereference`: Follow symbolic links
`-t, --terse`: Display the information in terse form
Common format fields: `%n`, `%N`, `%s`, `%b`, `%B`, `%F`, `%A`, `%a`, `%h`, `%i`, `%d`, `%D`, `%o`, `%u`, `%g`, `%U`, `%G`, `%x/%X`, `%y/%Y`, `%z/%Z`, `%w/%W` | Windows-backed file status display; missing operands now also print the GNU-style `Try 'stat --help' for more information.` hint, and `-t`, `-c/--format`, plus `--printf` now follow GNU/uutils-style last-occurrence precedence, while owner/group and symlink details remain Windows approximations |
| `link` | ✅ Done | Medium | Create a hard link between two files | No regular options | Hard-link creation; missing-source failures and existing-destination failures now use GNU-shaped `cannot create link 'LINK' to 'FILE'` diagnostics instead of raw Win32 error codes, wrong operand counts now collapse to the uutils-shaped `2 values required` diagnostic, option parsing for this optionless command now emits GNU-style `unrecognized option` help hints, `-V/--version` now succeeds, and source wildcards now follow the shared file-input policy: exact-one match expands, multi-match collapses back to the same `2 values required` operand-count failure a shell-expanded call would trigger, and zero-match falls back to the literal path |
| `unlink` | ✅ Done | Low | Remove a single file | No options | File removal; missing-path and directory failures now use GNU-shaped `cannot unlink` diagnostics instead of raw Win32 error codes, operand errors keep their help hint on stderr and now name the offending extra operand, unknown options on this optionless command now emit GNU-style `unrecognized option` help hints, `-V/--version` now succeeds, wildcard inputs that expand to multiple paths now fail with a GNU-style `extra operand` hint, unmatched wildcard inputs fall back to the literal path, and directory symlinks/junctions are now removed as links rather than deleting their targets |
| `truncate` | ✅ Done | Low | Shrink or extend the size of a file | `-c, --no-create`: Do not create files
`-s, --size=SIZE`: Set or adjust the file size by SIZE bytes
`-r, --reference=RFILE`: Base the size of FILE on the size of RFILE | File size modification |
| `sync` | ✅ Done | Low | Synchronize cached writes to persistent storage | `-d, --data`: Sync only file data for the named files
`-f, --file-system`: Sync the file systems that contain the named files | File system synchronization; GNU `sync`'s `-d/--data` and `-f/--file-system` option surface is now accepted, existing directory operands now succeed for plain `sync` and `--data`, `--data` without file operands now fails with the uutils-shaped `--data needs at least one argument` diagnostic, `--data` and `--file-system` now fail together as mutually exclusive options, `--file-system` now accepts existing file and directory operands as filesystem references, invalid options now emit GNU-style `unrecognized option` help hints, and missing file operands are now all reported with GNU/uutils-shaped `error opening 'FILE': No such file or directory` diagnostics instead of stopping after the first failure; Windows still uses an approximation rather than true Unix filesystem sync semantics |
| `install` | ✅ Done | Medium | Copy files and set attributes | `-b, --backup[=CONTROL]`: Make a backup of each existing destination file
`-C, --compare`: Compare each pair of source and destination files
`-d, --directory`: Treat all arguments as directory names
`-D, --create-leading-dirs`: Create all leading components of DEST except the last
`-g, --group=GROUP`: Set group ownership
`-m, --mode=MODE`: Set permission mode
`-o, --owner=OWNER`: Set ownership
`-p, --preserve-timestamps`: Apply access/modification times of SOURCE files
`-s, --strip`: Strip symbol tables
`-t, --target-directory=DIRECTORY`: Install all SOURCE arguments into DIRECTORY
`-T, --no-target-directory`: Treat DEST as a normal file
`-v, --verbose`: Print the name of each directory as it is created | File installation with attributes |
| `find` | ✅ Done | High | Search for files in a directory hierarchy | `-name PATTERN`: Base file name matches shell pattern PATTERN
`-iname PATTERN`: Base file name matches shell pattern PATTERN, case-insensitive
`-path PATTERN`: Full path matches shell pattern PATTERN
`-ipath PATTERN`: Full path matches shell pattern PATTERN, case-insensitive
`-type X`: File is of type X (currently `f`, `d`, `l`)
`-size N`: File uses N units of space; supports `+N/-N/N` and `c/k/M/G` units
`-empty`: File or directory is empty
`-mtime N`: File data was last modified N*24 hours ago
`-mmin N`: File data was last modified N minutes ago
`-mindepth N`: Begin tests only after depth N
`-maxdepth N`: Descend at most N levels
`-print`: Print the full file name on standard output
`-print0`: Print the full file name followed by NUL
`-printf FORMAT`: Print selected GNU-style file fields (`%p`, `%f`, `%h`, `%H`, `%P`, `%d`, `%D`, `%F`, `%g`, `%G`, `%l`, `%o`, `%u`, `%U`, `%S`, `%y`, `%Y`, `%s`, `%b`, `%k`, `%m`, `%M`, `%n`, `%i`, `%A@`, `%B@`, `%C@`, `%T@`, plus the zero-padded local component subset `%A{Y,m,d,H,M,S,j}`, `%B{Y,m,d,H,M,S,j}`, `%C{Y,m,d,H,M,S,j}`, `%T{Y,m,d,H,M,S,j}`, `%%`) and common escapes including GNU-style `\c` plus octal `\NNN`
`-prune`: Skip descending into directories in the current traversal
`-quit`: Stop the search immediately
`-L`: Follow symbolic links during traversal
`-H`: Follow command-line symlink roots only; traversal-time symlinks still require `-L`
`-delete`: Delete matched files/directories using depth-first traversal
`-exec COMMAND {} ;`: Execute once per match with `{}` replacement
`-exec COMMAND {} +`: Batch matched paths at the end of COMMAND
`-ok COMMAND {} ;`: Prompt before executing once per match
`-ok COMMAND {} +`: Prompt once before executing a batched command | File searching with GNU-style expression precedence and short-circuiting; current-directory-rooted default `-print` / `-print0` output now uses a Microsoft-style `.\` prefix while keeping the remainder of the relative path stable; junction-style directory reparse points are treated as link-like entries for `-type l` and related `-printf` fields, `%S` reports the Win32 allocated-size to logical-size ratio as the closest sparseness analogue for regular files, the `%A/%B/%C/%T` component subset now exposes a deterministic local time surface beyond the `@` forms, and some deeper GNU regex and `-printf` semantics still remain open |
| `xargs` | ✅ Done | High | Build and execute command lines from input | `-n, --max-args=MAX-ARGS`: Use at most MAX-ARGS arguments per command line
`-L, --max-lines=MAX-LINES`: Use at most MAX-LINES nonblank input lines per command line
`-l[LINES]`: Deprecated alias for `-L`; bare form defaults to 1 line
`-I R-STR`: Replace occurrences of R-STR in the initial arguments with names read from standard input
`-i, --replace[=R-STR]`: Deprecated alias for `-I`; bare form defaults to `{}`
`-P, --max-procs=MAX-PROCS`: Run at most MAX-PROCS processes at a time
`-a, --arg-file=FILE`: Read items from FILE instead of standard input
`-E EOF`: Set the logical EOF string
`-e[EOF], --eof[=EOF]`: Deprecated alias for `-E`; bare form leaves EOF disabled
`--show-limits`: Display command-line length limits
`-t, --verbose`: Print the command line on standard error before executing it
`-0, --null`: Input items are terminated by a null character instead of white space
`-d, --delimiter=DELIM`: Input items are terminated by DELIM instead of white space
`-o, --open-tty`: Reopen standard input as the console for children
`-r, --no-run-if-empty`: Do not run the command when input is empty
`-x, --exit`: Exit if the size limit is exceeded
`--process-slot-var=VAR`: Export a slot variable to children | Execute commands from input, SmallVector optimization; stdin items still stay literal data, while command-template arguments now consume the shared wildcard policy so `xargs cmd ... *.txt` behaves closer to a shell-expanded GNU call on Windows and still falls back to the literal token when the glob has no matches; parent-directory wildcard segments such as `dir*\\*.txt` and `dir?\\*.txt` now expand too instead of staying spuriously literal; malformed `-d` escape forms such as `\\x` and unknown named escapes now return specific delimiter-escape diagnostics instead of the older generic single-character error |
### Text Processing
| Command | Status | Priority | Description | Parameters/Options | Implementation Notes |
|---------|--------|----------|-------------|-------------------|---------------------|
| `echo` | ✅ Done | High | Display a line of text | `-n`: Do not output the trailing newline
`-e`: Enable interpretation of backslash escapes
`-E`: Disable interpretation of backslash escapes
`-u, --upper`: Convert text to uppercase
`-r, --repeat N`: Repeat output N times | Implemented with pipeline architecture, serves as reference implementation, supports escape sequences including `\n`, `\t`, `\xHH`, `\uHHHH`, GNU old-style octal escapes like `\43` and `\101`, bare `echo` now matches GNU/uutils by succeeding with a single trailing newline instead of treating empty args as an error, `-e` / `-E` now follow GNU/uutils last-occurrence precedence, unknown or incomplete escapes such as `\ ` and `\x` without hex digits now keep their leading backslash like GNU/uutils, `\xFF` style non-UTF-8 bytes and UTF-8 byte sequences such as `\xf0\x9f\x98\x82` are now covered by tests, and `POSIXLY_CORRECT` now enables escape processing by default while still honoring `-n`, ignoring `-E`, and treating non-leading-`-n` option-like arguments such as `--help`, `--version`, and `-nE` as literal text |
| `grep` | ✅ Done | High | Print lines matching a pattern | `-E, --extended-regexp`: Interpret PATTERNS as extended regular expressions
`-F, --fixed-strings`: Interpret PATTERNS as fixed strings
`-G, --basic-regexp`: Interpret PATTERNS as basic regular expressions
`-e, --regexp=PATTERNS`: Use PATTERNS for matching; repeatable
`-f, --file=FILE`: Read patterns from FILE; repeatable
`-i, --ignore-case`: Ignore case distinctions
`-w, --word-regexp`: Match only whole words
`-x, --line-regexp`: Match only whole lines
`-z, --null-data`: Use NUL-delimited records
`-v, --invert-match`: Invert the sense of matching
`-m, --max-count=NUM`: Stop after NUM selected lines
`-b, --byte-offset`: Prefix byte offsets
`-n, --line-number`: Prefix line numbers
`-H, --with-filename`: Print file name prefixes
`-h, --no-filename`: Suppress file name prefixes
`-o, --only-matching`: Print only matching parts
`-q, --quiet`: Suppress normal output
`-r, --recursive`: Recurse into directories
`-R, --dereference-recursive`: Recurse and follow directory symlinks
`--include=GLOB`, `--exclude=GLOB`, `--exclude-from=FILE`, `--exclude-dir=GLOB`: Filter searched files
`-A/-B/-C`: Print context
`--group-separator=SEP`, `--no-group-separator`: Control context group separators
`--binary-files=TYPE`, `-a`, `-I`: Binary-file policy
`-D, --devices=ACTION`: Use `read` or `skip` for devices/FIFOs/sockets
`--color`: Highlight matches | Pattern matching with regex support, wildcard file operands, repeatable option storage, and SmallVector optimization |
| `sort` | ✅ Done | Medium | Sort lines of text files | `-b, --ignore-leading-blanks`: Ignore leading blanks
`-d, --dictionary-order`: Consider only blanks and alphanumerics
`-f, --ignore-case`: Fold lower case to upper case characters
`-g, --general-numeric-sort`: Compare according to general numeric value
`-h, --human-numeric-sort`: Compare according to human-readable numeric value
`-i, --ignore-nonprinting`: Ignore nonprinting characters
`-k, --key`: Repeatable key sort using `F[.C][OPTS][,F[.C][OPTS]]` ranges
`-M, --month-sort`: Sort by month name
`-n, --numeric-sort`: Compare according to string numerical value
`-r, --reverse`: Reverse the result of comparisons
`-R, --random-sort`: Random sort order
`--random-source=FILE`: Get deterministic random bytes from FILE
`-S, --buffer-size=SIZE`: Accept GNU SIZE forms as a memory hint
`--parallel=N`: Accept a validated concurrency hint
`--batch-size=N`: Accept a validated merge hint
`--compress-program=PROG`: Accept a validated non-empty compression hint
`-T, --temporary-directory=DIR`: Accept an existing-directory temporary hint
`-s, --stable`: Stable sort
`-u, --unique`: With -c, check for strict ordering
`-C, --check-silent`: Quietly check whether input is sorted
`-t, --field-separator`: Use SEP instead of non-blank to blank transition
`-z, --zero-terminated`: Line delimiter is NUL, not newline
`-o FILE`: Write the result to FILE instead of standard output | Sorting with ordered multi-key, key ranges, character positions, common per-key modifiers, GNU-style quiet check mode, plus validated `--parallel`, `--batch-size`, `--compress-program`, and `-T/--temporary-directory` hints that currently do not change the single-threaded merge/temp-file implementation |
| `wc` | ✅ Done | Medium | Print newline, word, and byte counts for each file | `-c, --bytes`: Print the byte counts
`-l, --lines`: Print the newline counts
`-w, --words`: Print the word counts
`-m, --chars`: Print the character counts
`-L, --max-line-length`: Print the maximum display width
`--files0-from=FILE`: Read file names from a NUL-separated list
`--total=WHEN`: Control how totals are printed | Character counting with multiple modes, SmallVector optimization |
| `head` | ✅ Done | Low | Output the first part of files | `-c, --bytes=[-]NUM`: Print the first N bytes, or count backward from the end with a negative value
`-n, --lines=[-]NUM`: Print the first N lines, or count backward from the end with a negative value
`-q, --quiet, --silent`: Never print headers giving file names
`-v, --verbose`: Always print headers giving file names
`-z, --zero-terminated`: Line delimiter is NUL, not newline | File head extraction with byte/line options, SmallVector optimization |
| `tail` | ✅ Done | Low | Output the last part of files | `-c, --bytes=[+]NUM`: Output the last N bytes, or start from an offset with a positive value
`-n, --lines=[+]NUM`: Output the last N lines, or start from an offset with a positive value
`-q, --quiet, --silent`: Never print headers giving file names
`-v, --verbose`: Always print headers giving file names
`-z, --zero-terminated`: Line delimiter is NUL, not newline
`-f, --follow`: Output appended data as the file grows
`--follow=name`: Follow by file name instead of descriptor
`-F`: Same as `--follow=name --retry`
`-s, --sleep-interval=SECONDS`: Pause between follow iterations
`--pid=PID`: Stop following after PID dies
`--retry`: Keep trying to open inaccessible files
`--use-polling`: Explicitly select polling follow mode
`--max-unchanged-stats=N`: Reopen an unchanged followed name after N iterations | File tail extraction with follow-by-name support; the `-F` / `--follow=descriptor|name` family now follows last-occurrence precedence, and `--use-polling` maps to the current polling-based follow implementation |
| `sed` | ✅ Done | Medium | Stream editor for filtering and transforming text | `-e, --expression`: Add SCRIPT to the commands to be executed; repeatable and order-preserving with `-f`
`-f, --file`: Add the contents of SCRIPT-FILE to the commands; repeatable and order-preserving with `-e`
`-n, --quiet, --silent`: Suppress automatic printing of pattern space
`-i, --in-place`: Edit files in place | Text stream editing with ordered repeatable script support, SmallVector optimization |
| `uniq` | ✅ Done | Medium | Report or omit repeated lines | `-c, --count`: Prefix lines by the number of occurrences
`-d, --repeated`: Only print duplicate lines, one for each group
`-D, --all-repeated[=METHOD]`: Print all repeated lines for each group
`-f, --skip-fields`: Avoid comparing the first N fields
`-i, --ignore-case`: Ignore differences in case when comparing
`-s, --skip-chars`: Avoid comparing the first N characters
`--group[=METHOD]`: Group repeated lines in the output
`-u, --unique`: Only print unique lines
`-w, --check-chars`: Compare no more than N characters in lines
`-z, --zero-terminated`: Line delimiter is NUL, not newline | Duplicate line detection and filtering, SmallVector optimization; grouping modes are wired, while exact GNU separator edge cases still need polish |
| `cut` | ✅ Done | Medium | Remove sections from each line of files | `-b, --bytes`: Cut by byte position
`-c, --characters`: Cut by character position
`-d, --delimiter`: Use DELIM instead of TAB for field delimiter
`-w`: Use runs of spaces or tabs as field delimiters (Microsoft/FreeBSD extension)
`-f, --fields`: Select only these fields
`--complement`: Select the complement of specified bytes, characters, or fields
`--output-delimiter=STRING`: Use STRING between selected fields or byte/character ranges
`-s, --only-delimited`: Do not print lines not containing delimiters
`-z, --zero-terminated`: Line delimiter is NUL, not newline | Field, byte, and character extraction; `-w` now follows Microsoft's whitespace-field splitting shape, including TAB output and `-d` conflict handling |
| `ptx` | ✅ Done | Low | Produce a permuted index of file contents | `-f, --ignore-case`: Ignore case differences
`-r, --references`: Output word references only
`-w, --width`: Set output width | Permuted index generation |
| `expand` | ✅ Done | Low | Convert tabs to spaces | `-t, --tabs=tab1[,tab2]...`: Set tab stops
`-i, --initial`: Do not convert tabs after non-blanks | Tab to space conversion |
| `unexpand` | ✅ Done | Low | Convert spaces to tabs | `-t, --tabs=tab1[,tab2]...`: Set tab stops
`-a, --all`: Convert all whitespace, not just initial
`-f, --first-only`: Only convert the first run of spaces
`-U, --no-utf8`: Treat file input as raw 8-bit bytes | Space to tab conversion; default file reads strip a UTF-8 BOM, while `-U` preserves it |
| `fold` | ✅ Done | Low | Wrap each input line to fit specified width | `-w, --width=WIDTH`: Use WIDTH columns instead of 80
`-b, --bytes`: Count bytes rather than columns
`-c, --characters`: Count characters rather than columns
`-s, --spaces`: Break at spaces | Line wrapping; ordinary newline-delimited mode trims trailing `\r` from CRLF records, `-c` now counts UTF-8 code points without splitting multibyte sequences, and default column mode keeps common UTF-8 wide characters intact while treating them as two display columns |
| `fmt` | ✅ Done | Low | Simple optimal text formatter | `-w, --width=WIDTH`: Maximum line width (default 75)
`-T, --tab-width=TABWIDTH`: Measure tabs as TABWIDTH spaces while preserving tabs in output
`-p, --prefix=STRING`: Only format lines starting with STRING
`-P, --skip-prefix=STRING`: Leave matching lines unformatted
`-x, --exact-prefix`: Do not ignore leading whitespace for `-p`
`-X, --exact-skip-prefix`: Do not ignore leading whitespace for `-P`
`-c, --crown-margin`: Preserve crown margins
`-m, --preserve-headers`: Detect simple mail headers and continuation lines
`-t, --tagged-paragraph`: Preserve tagged paragraphs
`-s, --split-only`: Only split long lines
`-u, --uniform-spacing`: Fix spacing | Text formatting; prefix mode now preserves the matched prefix attachment, `-x` keeps indented lines out of `-p` matching, `-P/-X` cover the common skip-prefix cases we matched against Microsoft, `-m` now preserves simple `Header: value` blocks with merged continuation lines while using the wider wrap behavior we observed on Microsoft, and tab-indented paragraphs now follow the Microsoft/Coreutils default 8-column tab width unless `-T` overrides the measurement width |
| `nl` | ✅ Done | Low | Number lines of files | `-b, --body-numbering=STYLE`: Use STYLE for numbering body lines
`-n, --number-format=FORMAT`: Insert line numbers according to FORMAT
`-s, --number-separator=STRING`: Add STRING after (possible) line numbers
`-f, --footer-numbering=STYLE`: Footer numbering style
`-h, --header-numbering=STYLE`: Header numbering style
`-i, --line-increment=NUMBER`: Line increment
`-l, --join-blank-lines=NUMBER`: Join blank lines
`-v, --starting-line-number=NUMBER`: Starting line number
`-w, --number-width=NUMBER`: Number width | Line numbering |
| `paste` | ✅ Done | Low | Merge lines of files | `-d, --delimiters=LIST`: Reuse characters from LIST instead of TABs
`-s, --serial`: Paste one file at a time instead of in parallel
`-z, --zero-terminated`: End lines with NUL | Line merging |
| `pr` | ✅ Done | Low | Convert text files for printing | `+FIRST_PAGE[:LAST_PAGE]`: Begin [stop] printing with page FIRST_PAGE
`-C, --columns=NUM`: Output NUM columns and print columns down
`-a, --across`: Print columns across
`-d, --double-space`: Double-space the output
`-h, --header=HEADER`: Use a centered HEADER instead of filename
`-l, --length=PAGE_LENGTH`: Set the page length to PAGE_LENGTH lines
`-o, --indent=MARGIN`: Offset each line with MARGIN spaces
`-T, --omit-pagination`: Omit pagination controls | Text file formatting for printing |
| `tr` | ✅ Done | Medium | Translate or delete characters | `-c, -C, --complement`: Use the complement of SET1
`-d, --delete`: Delete characters in SET1
`-s, --squeeze-repeats`: Replace each sequence of a repeated character
`-t, --truncate-set1`: First truncate SET1 to length of SET2 | Character translation and deletion; operand-count diagnostics now distinguish missing `SET2`, `-d -s` missing the squeeze set, and delete-mode extra operands with GNU-style help hints |
| `rev` | ✅ Done | Low | Reverse lines of a file | No options | Line reversal |
| `tac` | ✅ Done | Low | Concatenate and print files in reverse | `-b, --before`: Attach the separator before instead of after
`-r, --regex`: Interpret the separator as a regular expression
`-s, --separator=STRING`: Use STRING as the separator | Reverse concatenation |
| `shuf` | ✅ Done | Low | Shuffle input lines | `-e, --echo`: Treat each ARG as an input line
`-i, --input-range=LO-HI`: Treat each number LO through HI as an input line
`-n, --head-count=COUNT`: Output at most COUNT lines
`-o, --output=FILE`: Write result to FILE instead of standard output
`--random-seed=STRING`: Use STRING for reproducible output
`--random-source=FILE`: Read random bytes from FILE
`-r, --repeat`: Allow repeated output
`-z, --zero-terminated`: Use NUL as line terminator | Line shuffling; `--random-seed` now follows the closer Microsoft/uutils seeded algorithm surface for permutation and `-r` sampling, `--random-source` now follows the closer GNU/Microsoft entropy-recycling adapter for repeat sampling and shuffle selection, repeated `-n/--head-count` now takes the lowest supplied count, and `--random-seed` is rejected together with `--random-source` |
| `split` | ✅ Done | Low | Split a file into pieces | `-l, --lines=NUMBER`: Put NUMBER lines per output file
`-b, --bytes=SIZE`: Put SIZE bytes per output file
`-C, --line-bytes=SIZE`: Put SIZE bytes per output file without splitting lines
`--filter=COMMAND`: Run COMMAND on each output file
`-n, --number=CHUNKS`: Produce CHUNKS chunks
`-a, --suffix-length=N`: Generate suffixes of length N
`-d, --numeric-suffixes[=FROM]`: Use numeric suffixes
`-x, --hex-suffixes[=FROM]`: Use hexadecimal suffixes
`--additional-suffix=SUFFIX`: Append SUFFIX to output files
`-e, --elide-empty-files`: Do not generate empty output files
`-t, --separator=SEP`: Use SEP as the record separator
`-u, --unbuffered`: Flush output after each line
`--verbose`: Print output file names | File splitting; the input operand uses the shared wildcard policy and ambiguous matches are rejected unless they resolve to exactly one file, while a third positional operand now fails with a GNU-style `extra operand` help hint |
| `csplit` | ✅ Done | Low | Split a file into context-determined pieces | `-f, --prefix=PREFIX`: Use PREFIX as output file name prefix
`-b, --suffix-format=FORMAT`: Use FORMAT for suffixes
`-n, --digits=DIGITS`: Use specified number of digits
`-k, --keep-files`: Do not remove output files on errors
`--suppress-matched`: Suppress matching lines in output files
`-z, --elide-empty-files`: Elide empty output files
`-s, -q, --quiet, --silent`: Do not print output file sizes | Context-determined file splitting; the input operand uses the shared wildcard policy and ambiguous matches are rejected unless they resolve to exactly one file, missing input/pattern diagnostics now include the GNU-style help hint, and line-number patterns with `--suppress-matched` now preserve GNU/uutils-style empty-tail behavior |
| `join` | ✅ Done | Low | Join lines of two files on a common field | `-1 FIELD`: Join on this FIELD of file 1
`-2 FIELD`: Join on this FIELD of file 2
`-a FILE-NUMBER`: Print unpairable lines from file NUMBER
`--check-order`: Check that input is correctly sorted
`--nocheck-order`: Do not check sort order
`-e STRING`: Replace empty output fields with STRING
`--header`: Treat first line of each file as header
`-i, --ignore-case`: Ignore case when comparing keys
`-j FIELD`: Join on FIELD in both files
`-o FIELD-LIST`: Output fields according to FIELD-LIST
`-t, --separator=CHAR`: Use CHAR as input and output field separator
`-v FILE-NUMBER`: Print only unpairable lines from file NUMBER
`-z, --zero-terminated`: Use NUL as line terminator | Line joining |
| `comm` | ✅ Done | Low | Compare two sorted files line by line | `-1`: Suppress lines unique to FILE1
`-2`: Suppress lines unique to FILE2
`-3`: Suppress lines that appear in both files
`--check-order`: Check that input is correctly sorted
`--nocheck-order`: Do not check sort order
`--output-delimiter=STRING`: Use STRING between columns
`--total`: Print totals
`-z, --zero-terminated`: Use NUL as line terminator | Sorted file comparison |
### System Information
| Command | Status | Priority | Description | Parameters/Options | Implementation Notes |
|---------|--------|----------|-------------|-------------------|---------------------|
| `which` | ✅ Done | High | Locate a command in PATH | `-a, --all`: Print all matching pathnames of each argument
`--read-alias`, `--skip-alias`: Read or skip alias expansion
`--read-functions`, `--skip-functions`: Read or skip shell function expansion
`--skip-dot`: Skip directories in PATH that start with a dot
`--show-dot`: Allow directories that start with a dot to be shown
`--skip-tilde`: Skip directories in PATH that start with a tilde
`--show-tilde`: Allow directories that start with a tilde to be shown
`--tty-only`: Show matches only on a tty | Path searching with PATHEXT support, SmallVector optimization |
| `env` | ✅ Done | Medium | Run a command in a modified environment | `-i, --ignore-environment`: Start with an empty environment
`-u, --unset=NAME`: Remove variable from the environment; repeatable
`-0, --null`: End each printed environment entry with NUL; rejected when COMMAND is present with GNU/uutils-style exit `125`
`-f, --file=FILE`: Load `.env`-style `NAME=VALUE` pairs before `-u` and command-line assignments; blank lines and `#` comments are ignored
`-S, --split-string=S`: Split S into arguments using the current lightweight parser; unterminated quotes now fail with exit `125`
`-v, --debug`: Emit processing diagnostics on standard error; repeated debug flags such as `-vv` also dump raw input arguments
`-a, --argv0=STRING`: Override the child process `argv[0]` while still executing the original program
`-C, --chdir=DIR`: Change working directory before running COMMAND; GNU-style usage requires that a command be present
`NAME=VALUE`: Add or override an environment variable
`COMMAND [ARG]...`: Run COMMAND with the modified environment | Prints or executes with a materialized Windows environment block; parse-time invalid options now also return GNU/uutils-style exit `125` with the standard help hint, `-f/--file` now loads simple trimmed `.env` entries before `-u` and command-line `NAME=VALUE`, file-open failures return a regular command failure instead of a usage error, `-a/--argv0`, `-C/--chdir`, and `-S/--split-string` now follow last-occurrence precedence, `-0/--null` is limited to environment-printing mode and now fails with `cannot specify --null (-0) with command` when combined with a command, missing child commands now report a GNU-shaped `failed to run command 'CMD': ...` diagnostic while preserving the conventional `127` not-found exit, and full GNU `-S` parsing plus remaining GNU debug/signal details remain gaps |
| `pwd` | ✅ Done | High | Print working directory | `-L, --logical`: Use an absolute `PWD` from the environment when it still names the current directory
`-P, --physical`: Avoid all symlinks | Working directory display; `-L` now prefers `PWD` only when it is absolute, still resolves to the current directory, and contains no `.` / `..` components, `POSIXLY_CORRECT` now switches bare `pwd` to the logical default, `-L/-P` follow last-occurrence precedence, and extra non-option operands now warn with GNU-shaped `ignoring non-option arguments` stderr output |
| `ps` | ✅ Done | High | Report process status | `-e, -A`: Select all processes
`-a`: Select all processes except both session leaders and processes not associated with a terminal
`-x`: Select processes without controlling ttys
`-f`: Full-format listing
`-l`: Long format
`-u USER`: Select by effective user ID or name
`-w`: Wide output
`--no-headers`: Print no header
`--sort=KEY`: Sort by column | Process listing and filtering; this is a repo-local implementation, not a GNU Coreutils manual page |
| `tee` | ✅ Done | Medium | Read from stdin and write to stdout and files | `-a, --append`: Append to the given FILEs, do not overwrite
`-i, --ignore-interrupts`: Ignore interrupt signals
`-p, --diagnose`: Write errors to standard error as they occur | Standard input/output redirection, SmallVector optimization |
| `chmod` | ✅ Done | Medium | Change file mode bits | `-c, --changes`: Like verbose but report only when a change is made
`-f, --silent, --quiet`: Suppress most error messages
`-v, --verbose`: Output a diagnostic for every file processed
`-R, --recursive`: Change files and directories recursively
`--reference=RFILE`: Use RFILE's mode instead of MODE values | File permission modification; file operands use the shared wildcard policy, `-R --preserve-root /` now stops with the GNU/uutils-style failsafe, `--reference=RFILE FILE...` now copies the reference file's Windows read-only approximation with GNU-shaped missing-reference diagnostics, malformed modes such as `u+gr` now fail before file access with the GNU-style help hint, and GNU-style negative symbolic modes such as `-w`, `file -w`, and repeated `-w -w` are now accepted |
| `chcon` | ✅ Done | Medium | Change SELinux file context | `--reference=RFILE`: Use RFILE's security context
`-u, --user=USER`: Set the user component
`-r, --role=ROLE`: Set the role component
`-t, --type=TYPE`: Set the type component
`-l, --range=RANGE`: Set the range component
`-R, --recursive`: Operate on files and directories recursively
`-H`, `-L`, `-P`, `-h`, `--dereference`: GNU-compatible symlink traversal/dereference surface
`-v, --verbose`: Output a diagnostic for every file processed | Windows compatibility placeholder: validates the GNU-shaped command line surface and existing file operands, then reports that SELinux file contexts are not supported on Windows |
| `chroot` | ✅ Done | Medium | Change the root directory | `--groups=GROUP1,GROUP2...`: Specify supplementary groups
`--userspec=USER:GROUP`: Specify user and group before running COMMAND
`--skip-chdir`: Do not change working directory to `/` after changing root
`NEWROOT [COMMAND [ARG]...]`: GNU operand form | Windows compatibility placeholder: validates the GNU-shaped command line surface and that `NEWROOT` exists as a directory, then reports that changing the root directory is not supported on Windows |
| `chown` | ✅ Done | Medium | Change file owner and group | `-c, --changes`: Like verbose but report only when a change is made
`-f, --silent, --quiet`: Suppress most error messages
`-v, --verbose`: Output a diagnostic for every file processed
`-R, --recursive`: Change files and directories recursively
`--from=CURRENT_OWNER:CURRENT_GROUP`: Change only from the current owner/group
`--reference=RFILE`: Use RFILE's owner and group instead of USER:GROUP | File ownership modification; explicit `OWNER` / `GROUP` names and the current-owner/group names supplied to `--from` are now validated up front so invalid names fail with GNU-shaped `invalid user` / `invalid group` diagnostics before traversal, malformed specs such as `::`, `..`, `1001:`, and `1001.` now fail with the closer GNU/uutils-shaped `invalid group` / `invalid spec` diagnostics, dot-separated forms such as `OWNER.` and `OWNER.GROUP` now emit the GNU/uutils-style `warning: '.' should be ':'` warning before proceeding, `--from` now filters existing targets by their current Windows owner/group before applying `--reference` or continuing with a direct change attempt, mismatching `--from` filters now keep the target unchanged and `-v` reports retained ownership, matching `--from` filters no longer emit the old Windows-placeholder `not supported` diagnostic, direct no-op specs such as `:` and `CURRENT_OWNER:` now also report retained ownership instead of a fake `changing ownership ... to` line, missing reference files now report `failed to get attributes of 'RFILE': No such file or directory`, `-v --reference=RFILE FILE...` now emits a retained-ownership diagnostic on stderr, and `--preserve-root -R /` now stops before traversal with the GNU/uutils-style two-line failsafe diagnostic |
| `chgrp` | ✅ Done | Medium | Change group ownership | `-c, --changes`: Like verbose but report only when a change is made
`-f, --silent, --quiet`: Suppress most error messages
`-v, --verbose`: Output a diagnostic for every file processed
`-R, --recursive`: Change files and directories recursively
`--from=GROUP`: Change only if the current group matches GROUP
`--reference=RFILE`: Use RFILE's group instead of GROUP | File group ownership modification; invalid `GROUP` operands now fail early with the GNU/uutils-shaped `invalid group: 'GROUP'` diagnostic plus the standard help hint, invalid `--from=GROUP` operands now fail with the matching uutils-shaped `invalid user: 'GROUP'` diagnostic, `--from=GROUP` now filters each existing target by its current Windows group name before applying `--reference` or a direct change attempt, numeric `--from=gid` and `--from=:gid` forms are now accepted and matched against the target group SID's final RID as a Windows approximation, missing `--reference=RFILE` files now report `failed to get attributes of 'RFILE': No such file or directory`, `--reference=RFILE FILE...` accepts the GNU operand form and validates the reference file on Windows, `-v --reference=RFILE FILE...` emits a retained-group diagnostic on stderr only when the `--from` filter matches, `--preserve-root -R /` now stops before traversal with the GNU/uutils-style two-line failsafe diagnostic, and the current implementation still treats actual group changes as Windows-limited behavior |
| `ln` | ✅ Done | Medium | Make links between files | `-s, --symbolic`: Make symbolic links instead of hard links
`-f, --force`: Remove existing destination files
`-i, --interactive`: Prompt whether to remove destinations
`-v, --verbose`: Print name of each linked file
`-n, --no-dereference`: Treat LINK_NAME as a normal file if it is a symbolic link to a directory
`-t, --target-directory=DIRECTORY`: Create links in DIRECTORY
`-T, --no-target-directory`: Treat LINK_NAME as a normal file always | File linking (hard/symbolic); `ln TARGET` now creates the link in the current directory using `basename(TARGET)`, `ln SOURCE DIR` now treats an existing second-operand directory as the target directory unless `-T` is active, missing-source failures, existing-target failures, and forced remove failures now report GNU-shaped text instead of raw Win32/local wording, multi-operand invocation follows GNU `TARGET... DIRECTORY` semantics instead of treating one source as many direct targets, and `-t` / `-T` now conflict explicitly |
| `diff` | ✅ Done | Medium | Compare files line by line | `-u, --unified=NUM`: Output NUM (default 3) lines of unified context
`-q, --brief`: Output only whether files differ
`-i, --ignore-case`: Ignore case differences in file contents
`-w, --ignore-all-space`: Ignore all white space
`-B, --ignore-blank-lines`: Ignore changes whose lines are all blank
`-y, --side-by-side`: Output in two columns
`-r, --recursive`: Recursively compare any subdirectories [NOT SUPPORT] | File comparison; file operands use the shared wildcard policy, must resolve to exactly two files, and now reject extra operands with a GNU-style help hint |
| `diff3` | ✅ Done | Low | Compare three files | `-e`: Output an ed script
`-3`: Like -e, but incorporate changes from the third file
`-m, --merge`: Output the merged file
`-i`: Like -e, but bracket changes
`-A`: Incorporate all changes from older to yours
`-E`: Ignore changes from older to yours
`-X`: Overwrite overlapping changes from older to yours | Three-way file comparison; file operands use the shared wildcard policy, must resolve to exactly three files, and now reject extra operands with a GNU-style help hint |
| `sdiff` | ✅ Done | Low | Side-by-side merge of file differences | `-o FILE`: Write output to FILE
`-w NUM`: Set output width to NUM columns
`-l`: Print only the left column when lines are common
`-s, --suppress-common-lines`: Do not print common lines
`-E`: Ignore tab expansion
`-b`: Ignore changes in the amount of white space
`-W`: Ignore all white space
`-B`: Ignore changes whose lines are all blank | Side-by-side diff; empty files are accepted, file operands now reject extra operands with a GNU-style help hint, and file-like wildcards resolve before the fixed two-file arity check |
| `patch` | ✅ Done | Medium | Apply a diff file to an original | `-p NUM`: Strip NUM leading components from file names
`-i, --input=PATCHFILE`: Read patch from PATCHFILE
`-d, --directory=DIR`: Change to DIR
`-R, --reverse`: Assume patch was created with old and new files swapped
`-N, --forward`: Assume patch was created with old and new files swapped | Patch file application |
| `cmp` | ✅ Done | Low | Compare two files byte by byte | `-b, --print-bytes`: Print differing bytes
`-i, --ignore-initial=SKIP` / `-i SKIP1:SKIP2`: Skip the specified initial bytes from one or both inputs
`-l, --verbose`: Output byte numbers and differing byte values for every difference
`-n, --bytes=LIMIT`: Compare at most LIMIT bytes
`-s, --quiet`: Suppress normal output
`FILE1 FILE2 [SKIP1 [SKIP2]]`: GNU positional skip operands are accepted | Byte comparison; default difference output now includes both byte and line numbers, `-l/--verbose` lists every differing byte using GNU-style octal values relative to the comparison start, the `-l/--verbose` and `-s/--quiet` output-mode family now follows GNU/uutils-style last-occurrence precedence, GNU positional `SKIP1`/`SKIP2` plus `-i SKIP1:SKIP2` now work, skip counts accept GNU-style decimal/octal/hex prefixes with common byte suffixes, and skipping past the shorter file no longer underflows the comparison range |
| `file` | ✅ Done | Medium | Determine file type | `-b, --brief`: Do not prepend filenames to output lines
`-i, --mime`: Output mime type strings
`-z, --compress`: Try to look inside compressed files
`--mime-type`: Output the MIME type only
`--mime-encoding`: Output the MIME encoding only | File type detection |
| `cksum` | ✅ Done | Low | CRC checksum and byte counts | `-a, --algorithm=TYPE`: Select `sysv`, `bsd`, or `crc`
`-c, --check=FILE`: Read and verify checksums from FILE
`--ignore-missing`: Skip missing listed files during check mode
`-q, --quiet`: Suppress successful `OK` lines during check mode
`-s, --status`: Suppress normal check-mode output and use exit status
`-w, --warn`: Report malformed checksum lines with locations
`--strict`: Fail when malformed checksum lines are present
`--tag`: Emit BSD-style tagged output
`--untagged`: Force untagged output
`-z, --zero`: End output records with NUL
`--raw`: Emit raw digest bytes
`--base64`: Emit base64 digest bytes
`-l, --length=BITS`: Select digest length when supported
`--debug`: Print debug output | Checksum calculation; check mode now verifies untagged size fields, supports GNU-style `--quiet` / `--status`, and treats malformed check lines like GNU with `--warn` / `--strict` |
| `sum` | ✅ Done | Low | Print checksum and block counts | `-r`: Use BSD checksum format
`-s`: Use System V checksum format | Legacy checksum compatibility |
| `md5sum` | ✅ Done | Low | Compute and check MD5 message digest | `-b, --binary`: Read in binary mode
`-c, --check`: Read MD5 sums from the FILEs and check them
`--tag`: Create a BSD-style checksum
`-t, --text`: Read in text mode
`-z, --zero`: End each output line with NUL | MD5 checksum |
| `sha1sum` | ✅ Done | Low | Compute and check SHA1 message digest | `-b, --binary`: Read in binary mode
`-c, --check`: Read SHA1 sums from the FILEs and check them
`--tag`: Create a BSD-style checksum
`-t, --text`: Read in text mode
`-z, --zero`: End each output line with NUL | SHA1 checksum |
| `sha224sum` | ✅ Done | Low | Compute and check SHA224 message digest | `-b, --binary`: Read in binary mode
`-c, --check`: Read SHA224 sums from the FILEs and check them
`--tag`: Create a BSD-style checksum
`-t, --text`: Read in text mode
`-z, --zero`: End each output line with NUL | SHA224 checksum |
| `sha256sum` | ✅ Done | Low | Compute and check SHA256 message digest | `-b, --binary`: Read in binary mode
`-c, --check`: Read SHA256 sums from the FILEs and check them
`--tag`: Create a BSD-style checksum
`-t, --text`: Read in text mode
`-z, --zero`: End each output line with NUL | SHA256 checksum |
| `sha384sum` | ✅ Done | Low | Compute and check SHA384 message digest | `-b, --binary`: Read in binary mode
`-c, --check`: Read SHA384 sums from the FILEs and check them
`--tag`: Create a BSD-style checksum
`-t, --text`: Read in text mode
`-z, --zero`: End each output line with NUL | SHA384 checksum |
| `sha512sum` | ✅ Done | Low | Compute and check SHA512 message digest | `-b, --binary`: Read in binary mode
`-c, --check`: Read SHA512 sums from the FILEs and check them
`--tag`: Create a BSD-style checksum
`-t, --text`: Read in text mode
`-z, --zero`: End each output line with NUL | SHA512 checksum |
| `b2sum` | ✅ Done | Low | Compute and check BLAKE2 message digest | `-b, --binary`: Read in binary mode
`-c, --check`: Read BLAKE2 sums from the FILEs and check them
`--tag`: Create a BSD-style checksum
`-t, --text`: Read in text mode
`-z, --zero`: End each output line with NUL | BLAKE2 checksum |
| `base64` | ✅ Done | Low | Base64 encode/decode data | `-d, --decode`: Decode data
`-i, --ignore-garbage`: When decoding, ignore non-alphabet characters
`-w, --wrap=COLS`: Wrap encoded lines after COLS characters | Base64 encoding/decoding; extra file operands now follow GNU-style `extra operand 'FILE'` diagnostics and print the standard `Try 'base64 --help' for more information.` hint |
| `base32` | ✅ Done | Low | Base32 encode/decode data | `-d, --decode`: Decode data
`-w, --wrap=COLS`: Wrap encoded lines after COLS characters | Base32 encoding/decoding; extra file operands now follow GNU-style `extra operand 'FILE'` diagnostics and print the standard `Try 'base32 --help' for more information.` hint |
| `basenc` | ✅ Done | Low | Encode/decode data with various algorithms | `-d, --decode`: Decode data
`-b, --base64`: Base64
`-z, --z85`: Z85
`-w, --wrap=COLS`: Wrap encoded lines after COLS characters | Various encoding/decoding; extra file operands now follow GNU-style `extra operand 'FILE'` diagnostics and print the standard `Try 'basenc --help' for more information.` hint |
| `xxd` | ✅ Done | Low | Make a hexdump or do the reverse | `-b, --bits`: Switch to bits (binary digits)
`-c, --cols COLS`: Format COLS octets per line
`-g, --groupsize BYTES`: Number of octets per group in normal output
`-l, --len LENGTH`: Stop after LENGTH octets
`-p, --ps`: Output in postscript continuous hexdump style
`-r, --reverse`: Reverse operation: convert (or patch) hexdump into binary
`-s, --seek OFFSET`: Start at OFFSET | Hexdump and reverse |
| `od` | ✅ Done | Low | Dump files in octal and other formats | `-A, --address-radix=RADIX`: Select the base in which file offsets are printed
`-j, --skip-bytes=BYTES`: Skip BYTES input bytes first
`-N, --read-bytes=BYTES`: Limit dump to BYTES bytes
`-t, --format=TYPE`: Select output format(s)
`-v, --output-duplicates`: Do not use * to mark line suppression
`-w, --width BYTES`: Output BYTES bytes per output line | Octal dump |
| `cpio` | ✅ Done | Low | Copy files to and from archives | `-o, --create`: Create the archive
`-i, --extract`: Extract files from an archive
`-t, --list`: List the contents of an archive
`-d, --make-directories`: Create leading directories where needed
`-m, --preserve-modification-time`: Retain previous file modification times when creating files | Archive copying |
| `dd` | ✅ Done | Medium | Convert and copy a file | `if=FILE`: Read from FILE instead of stdin
`of=FILE`: Write to FILE instead of stdout
`bs=BYTES`: Read and write up to BYTES bytes at a time
`ibs=BYTES`: Read up to BYTES bytes at a time
`obs=BYTES`: Write BYTES bytes at a time
`cbs=BYTES`: Convert BYTES bytes at a time [parsed]
`count=N`: Copy only N input blocks
`skip=N`: Skip N ibs-sized input blocks
`seek=N`: Skip N obs-sized output blocks
`conv=CONVS`: Supports `notrunc` and `sync`; accepts `noerror` as a placeholder
`status=none|noxfer|progress`: Control diagnostic output | File conversion and copying |
| `expr` | ✅ Done | Medium | Evaluate expressions | `--help`: Display help
`--version`: Output version information | Expression evaluation |
| `factor` | ✅ Done | Low | Print prime factors | No options | Prime factorization |
| `tsort` | ✅ Done | Low | Perform topological sort | No options | Topological ordering of pair lists |
| `seq` | ✅ Done | Low | Print a sequence of numbers | `-f, --format=FORMAT`: Use printf style floating-point FORMAT
`-s, --separator=STRING`: Use STRING to separate numbers
`-t, --terminator=STRING`: Use STRING instead of the final newline
`-w, --equal-width`: Equalize width by padding with leading zeroes | Sequence generation; missing and extra operands now include GNU-style help hints, `-w` now rejects an explicit `-f/--format` string with the GNU/uutils-style conflict diagnostic, `-t/--terminator` now replaces only the final output separator while leaving intermediate separators unchanged, and zero increments now use the closer GNU/uutils `invalid Zero increment value: 'ARG'` diagnostic |
| `yes` | ✅ Done | Low | Output a string repeatedly | `STRING...`: Strings to join with spaces before repeating | Repeated output; GNU/uutils-style multi-operand invocations now join all operands with single spaces instead of using only the first operand, and `-V/--version` now succeeds instead of being misparsed as an unknown option |
| `sleep` | ✅ Done | Low | Delay for a specified time | `NUMBER[SUFFIX]`: Pause for NUMBER seconds | Sleep delay; missing operands now include the GNU-style help hint, malformed or negative durations now use GNU-shaped `invalid time interval` diagnostics, multiple invalid duration operands are now all reported before the final help hint, leading whitespace remains accepted, and trailing whitespace is now rejected like GNU/uutils |
| `stdbuf` | ✅ Done | Medium | Run COMMAND with modified buffering operations for its standard streams | `-i, --input=MODE`: Adjust standard input stream buffering
`-o, --output=MODE`: Adjust standard output stream buffering
`-e, --error=MODE`: Adjust standard error stream buffering | Buffer modification; missing-command, invalid-mode, and invalid-option usage/parse failures now return GNU/uutils-style exit `125` while keeping the help hint on stderr, child arguments are now quoted with Windows `CreateProcessW` rules so spaces stay within one argv entry, and the implementation still only adjusts parent-process buffering |
| `shred` | ✅ Done | Medium | Overwrite a file to hide its contents | `-f, --force`: Change permissions to allow writing
`-n, --iterations=N`: Overwrite N times instead of the default (3)
`-s, --size=N`: Shred this many bytes
`-u, --remove`: Delete and truncate file after overwriting
`-v, --verbose`: Show progress
`-z, --zero`: Add a final overwrite with zeros | Secure file deletion |
| `pathchk` | ✅ Done | Low | Check whether file names are valid or portable | `-p, --portability`: Check based on POSIX
`-P, --posix`: Check based on POSIX
`--help`: Display help
`--version`: Output version information
GNU-shaped operand diagnostics: missing operand help hint stays on stderr
Current-filesystem checks accept normal Windows drive-letter absolute paths, repeated/trailing separators no longer trip false `empty file name` failures under `-P`-style checks, and the default empty-path diagnostic now uses the GNU/uutils-style `pathchk: '': No such file or directory` shape, including one line per invalid operand | Path validation |
| `tree` | ✅ Done | Medium | List contents of directories in a tree-like format | `-a, --all`: All files are listed
`-d, --directory-list`: List directories only
`-f, --full-path`: Print full path prefix for each file
`-L, --level=LEVEL`: Descend only level directories deep
`--help`: Display help
`--version`: Output version information | Tree display |
| `less` | ✅ Done | High | View file (or stdin) with scrollable page | `-E, --QUIT-AT-EOF`: Quit at EOF
`-F, --quit-if-one-screen`: Quit if entire file fits on first screen
`-R, --RAW-CONTROL-CHARS`: Output "raw" control characters
`-S, --chop-long-lines`: Chops long lines | File viewer |
| `cat` | ✅ Done | High | Concatenate files and print on the standard output | `-n, --number`: Number all output lines
`-b, --number-nonblank`: Number non-empty output lines
`-E, --show-ends`: Display $ at end of each line
`-s, --squeeze-blank`: Squeeze multiple adjacent empty lines
`-T, --show-tabs`: Display TAB characters as `^I` | Simple file reading and writing with pipeline structure, SmallVector optimization |
| `cp` | ✅ Done | High | Copy files and directories | `-i, --interactive`: Prompt before overwrite
`-r, --recursive`: Copy directories recursively
`-v, --verbose`: Explain what is being done
`-f, --force`: Force copy without prompt
`--strip-trailing-slashes`: Strip trailing `/` or `\` from each source operand before lookup | File system operations with error handling |
| `mv` | ✅ Done | High | Move (rename) files | `-i, --interactive`: Prompt before overwrite
`-I`: Prompt once before larger batches
`-v, --verbose`: Explain what is being done
`-f, --force`: Do not prompt before overwriting
`-n, --no-clobber`: Do not overwrite an existing file
`--interactive[=WHEN]`: GNU-style overwrite prompt mode with last-option precedence | File system operations with error handling, SmallVector optimization |
| `rm` | ✅ Done | High | Remove files or directories | `-f, --force`: Ignore nonexistent files and arguments, never prompt
`-i, --interactive`: Prompt before every removal
`-r, -R, --recursive`: Remove directories and their contents recursively
`-v, --verbose`: Explain what is being done | File system operations with error handling |
| `mkdir` | ✅ Done | High | Make directories | `-p, --parents`: No error if existing, make parent directories as needed
`-v, --verbose`: Print a message for each created directory
`-m, --mode`: Set file mode (as in chmod) | File system operations with error handling; missing operands now include the GNU-style help hint |
| `rmdir` | ✅ Done | Medium | Remove empty directories | `--ignore-fail-on-non-empty`: Ignore each failure to remove a directory that is non-empty
`-p, --parents`: Remove DIRECTORY and its ancestors
`-v, --verbose`: Print a message for each removed directory | File system operations with error handling; verbose output now uses the GNU/uutils-shaped `removing directory, 'DIR'` line before each attempted removal, including failed parent-cleanup attempts |
### Network
| Command | Status | Priority | Description | Parameters/Options | Implementation Notes |
|---------|--------|----------|-------------|-------------------|---------------------|
| `ping` | ❌ TODO | High | Send ICMP ECHO_REQUEST to network hosts | `-c COUNT`: Stop after sending COUNT ECHO_REQUEST packets
`-i INTERVAL`: Wait INTERVAL seconds between sending each packet | Not yet implemented |
| `curl` | ❌ TODO | Medium | Transfer data from or to a server | `-s, --silent`: Silent mode
`-o, --output`: Write output to a file instead of stdout | Not yet implemented |
| `wget` | ❌ TODO | Medium | Non-interactive network downloader | `-O, --output-document=FILE`: Write documents to FILE
`-q, --quiet`: Turn off wget's output | Not yet implemented |
### Testing and Terminal Control
| Command | Status | Priority | Description | Parameters/Options | Implementation Notes |
|---------|--------|----------|-------------|-------------------|---------------------|
| `test` | ✅ Done | High | Check file types and compare values | `-b FILE`: FILE exists and is block special
`-c FILE`: FILE exists and is character special
`-d FILE`: FILE exists and is a directory
`-e FILE`: FILE exists
`-f FILE`: FILE exists and is a regular file
`-g FILE`: FILE exists and is set-group-ID
`-G FILE`: FILE exists and is owned by the effective group ID
`-h FILE`: FILE exists and is a symbolic link
`-k FILE`: FILE exists and has its sticky bit set
`-L FILE`: FILE exists and is a symbolic link
`-O FILE`: FILE exists and is owned by the effective user ID
`-p FILE`: FILE exists and is a named pipe
`-r FILE`: FILE exists and read permission is granted
`-s FILE`: FILE exists and has a size greater than zero
`-S FILE`: FILE exists and is a socket
`-t FD`: File descriptor FD is opened on a terminal
`-u FILE`: FILE exists and its set-user-ID bit is set
`-w FILE`: FILE exists and write permission is granted
`-x FILE`: FILE exists and execute permission is granted
`-z STRING`: the length of STRING is zero
`-n STRING`: the length of STRING is nonzero
`STRING1 = STRING2`: the strings are equal
`STRING1 != STRING2`: the strings are not equal
`INTEGER1 -eq INTEGER2`: INTEGER1 is equal to INTEGER2
`INTEGER1 -ne INTEGER2`: INTEGER1 is not equal to INTEGER2
`INTEGER1 -gt INTEGER2`: INTEGER1 is greater than INTEGER2
`INTEGER1 -ge INTEGER2`: INTEGER1 is greater than or equal to INTEGER2
`INTEGER1 -lt INTEGER2`: INTEGER1 is less than INTEGER2
`INTEGER1 -le INTEGER2`: INTEGER1 is less than or equal to INTEGER2
`! EXPR`: EXPR is false
`EXPR1 -a EXPR2`: Both EXPR1 and EXPR2 are true
`EXPR1 -o EXPR2`: Either EXPR1 or EXPR2 is true | File type checking and value comparison |
| `[` | ✅ Done | High | Check file types and compare values (same as test) | Same as test | Alias for test |
| `test_bracket` | ✅ Done | High | Internal entry point for `[` | Same as test | Shared syntax and dispatch wrapper for `test` / `[` |
| `true` | ✅ Done | Low | Return a successful result | No options | Always returns 0 for normal execution, and `-V/--version` now succeeds instead of being misparsed as an unknown option |
| `false` | ✅ Done | Low | Return an unsuccessful result | No options | Always returns 1 for normal execution, and `-V/--version` now succeeds instead of being misparsed as an unknown option |
| `clear` | ✅ Done | High | Clear the terminal screen | No options | Uses system call to clear screen |
| `reset` | ✅ Done | Low | Reinitialize the terminal | No options | Terminal reset |
| `tput` | ✅ Done | Low | Initialize a terminal or query terminfo database | `STRING`: Terminfo capability to query | Terminal capability query |
| `tic` | ✅ Done | Low | Terminfo entry-description compiler | No options | Terminfo compilation |
| `toe` | ✅ Done | Low | Table of (terminfo) entries | No options | Terminfo table display |
| `tty` | ✅ Done | Low | Print the file name of the terminal connected to standard input | `-s, --silent`: Print nothing, only return an exit status
`--quiet`: Alias for `--silent` | Terminal file name display; extra operands and invalid options now keep GNU-shaped diagnostics plus the help hint on stderr with exit 2, non-tty stdin returns exit 1 in silent and non-silent modes, broken stdout during non-silent output now returns GNU/uutils-shaped exit 3, and tty detection still uses simplified Windows console detection |
| `stty` | ✅ Done | Medium | Change and print terminal line settings | `-a, --all`: Print all current settings
`-g, --save`: Print all current settings in stty-readable form
`-F, --file=DEVICE`: Open and use the specified DEVICE instead of stdin | Terminal settings |
| `infocmp` | ✅ Done | Low | Compare or print out terminfo descriptions | `-d, --differences`: Print differences
`-c, --compare`: Print comparisons
`-I, --use-terminfo`: Use the terminfo names | Terminfo comparison |
| `getconf` | ✅ Done | Low | Query system configuration variables | `-a, --all`: Print all configuration variables
`-v, --variable-specification`: Return variable based on variable specification | System configuration query |
| `locale` | ✅ Done | Low | Get locale-specific information | `-a, --all-locales`: List all available locales
`-m, --charmaps`: List available charmaps
`-c, --category-name`: List names of available categories
`-k, --keyword-name`: List names of available keywords | Locale information |
| `localedef` | ✅ Done | Medium | Compile locale definition files | `-f, --charmap=FILE`: Symbolic character names defined in FILE
`-i, --inputfile=FILE`: Locale definition file
`-u, --alias-file=FILE`: Alias file for locale names | Locale definition compilation |
| `tzset` | ✅ Done | Low | Initialize timezone information | No options | Timezone initialization |
| `iconv` | ✅ Done | Medium | Convert text from one encoding to another | `-f, --from-code=NAME`: Encoding of original text
`-t, --to-code=NAME`: Encoding for output
`-l, --list`: List all known coded character sets
`-c`: Omit invalid characters
`-s`: Suppress warnings | Encoding conversion |
| `cygpath` | ✅ Done | Medium | Convert Windows and POSIX path names | `-u, --unix`: Print Unix (POSIX) form of path
`-w, --windows`: Print Windows form of path
`-m, --mixed`: Print Windows form, with regular slashes
`-a, --absolute`: Output absolute path | Path conversion |
| `dos2unix` | ✅ Done | Low | Convert DOS line endings to Unix format | No options | Line ending conversion |
| `unix2dos` | ✅ Done | Low | Convert Unix line endings to DOS format | No options | Line ending conversion |
| `d2u` | ✅ Done | Low | Alias for dos2unix | No options | Line ending conversion |
| `u2d` | ✅ Done | Low | Alias for unix2dos | No options | Line ending conversion |
| `printf` | ✅ Done | High | Format and print data | `FORMAT`: Format string
`ARGUMENTS`: Arguments to format | Formatted output |
### System Utilities
| Command | Status | Priority | Description | Parameters/Options | Implementation Notes |
|---------|--------|----------|-------------|-------------------|---------------------|
| `date` | ✅ Done | Medium | Print or set system date/time | `-d, --date=STRING`: Display time described by STRING
`--debug`: Print date-parsing diagnostics
`-f, --file=DATEFILE`: Read date strings from a file
`-I, --iso-8601[=TIMESPEC]`: ISO 8601 output
`-r, --reference=FILE`: Use FILE's time
`--resolution`: Print time resolution
`-R, --rfc-email`: RFC 5322-style date output
`--rfc-3339=TIMESPEC`: RFC 3339-style output
`-s, --set=STRING`: Set the system time
`-u, --utc, --universal`: Print or set Coordinated Universal Time (UTC)
`+FORMAT`: Output format string | Date/time display and formatting |
| `df` | ✅ Done | Medium | Report file system disk space usage | `-h, --human-readable`: Print sizes in powers of 1024
`-H, --si`: Print sizes in powers of 1000
`-k`: Use 1K blocks
`-T, --print-type`: Print file system type
`-i, --inodes`: List inode-shaped information instead of block usage; Windows prints placeholder inode columns
File operands use the shared wildcard policy
`-t, --type=TYPE`, `-x, --exclude-type=TYPE`, `-a, --all`: tracked in the GNU parity ledger | Disk space reporting |
| `du` | ✅ Done | Medium | Estimate file space usage | `-a, --all`: Write counts for all files, not just directories
`-B, --block-size=SIZE`: Scale sizes by SIZE before printing
`-b, --bytes`: Equivalent to apparent-size with block size 1
`-c, --total`: Produce a grand total
`-d, --max-depth=N`: Print entries only if they are N or fewer levels below the command line argument
`-h, --human-readable`: Print sizes in powers of 1024
`--si`: Print sizes in powers of 1000
`-H, --dereference-args`: Accept GNU dereference-args surface on Windows
`-k`: Use 1K blocks
`-m`: Use 1M blocks
`-0, --null`: End each output record with NUL instead of newline
`-S, --separate-dirs`: Exclude subdirectory totals from each parent directory's reported size
`--time[=WORD]`: Show the latest selected timestamp for each emitted entry; supports `mtime`, `atime|access|use`, and `ctime|status`
`-X, --exclude-from=FILE`: Read exclude glob patterns from FILE
`--files0-from=FILE`: Read NUL-delimited path operands from FILE
`-s, --summarize`: Display only a total for each argument | File/directory size estimation; `--files0-from` rejects extra command-line paths, file operands otherwise use the shared wildcard policy, `--exclude-from` patterns feed the same matcher as `--exclude`, block counts round up, and `ctime`/`status` currently map to creation time on Windows |
| `dir` | ✅ Done | Medium | List directory contents in columns by default | `OPTION... FILE...`: Forward the GNU `dir` wrapper surface to `ls -C` | Wrapper around `ls` with column output as the default; forwarded argv now keeps the original option/operand order, so GNU wrapper options such as `-a` and `-d` actually reach `ls`, and single arguments containing spaces are preserved via Windows `CreateProcessW` quoting rules |
| `kill` | ✅ Done | High | Send a signal to processes | `-l, --list`: List all signal names
`-s, --signal=SIGNAL`: Send the specified signal
`-t, --table`: List signals in a table
`SIGNAL`: Signal number or name (e.g., -9, -KILL, -15, -TERM) | Process signal sending |
| `nice` | ✅ Done | Medium | Run a program with modified scheduling priority | `-n, --adjustment=N`: Add integer N to the scheduling priority
Legacy GNU adjustment forms such as `-1`, `--1`, and `-+1` are accepted before COMMAND
`--help`: Display help
`--version`: Output version information | Process priority modification; bare `nice` now prints the current niceness, explicit adjustments without a command now fail with the GNU/uutils-style `A command must be given with an adjustment.` usage error and exit `125`, legacy bare adjustments like `-1`, `--1`, and `-+1` now rewrite to GNU `-n` semantics before the command starts, huge positive/negative adjustments are clamped instead of failing in option parsing, invalid adjustment strings such as `-2+4` return exit `125` with a GNU-shaped usage error, invalid option parse failures now also return `125`, child arguments are now quoted with Windows `CreateProcessW` rules so spaces stay within a single argv entry, and missing child commands now report a GNU-shaped `failed to run command 'CMD': ...` diagnostic while preserving the conventional `127` not-found exit |
| `nohup` | ✅ Done | Medium | Run a command immune to hangups | `--help`: Display help
`--version`: Output version information
GNU-shaped operand/parse diagnostics: missing-operand and invalid-option help hints stay on stderr, and those usage errors return `127` under `POSIXLY_CORRECT` instead of the default `125` | Immune to hangups; child arguments are now quoted with Windows `CreateProcessW` rules so spaces stay within one argv entry, and missing command invocation now reports a GNU-shaped `failed to run command 'CMD': ...` diagnostic and preserves the conventional `127` not-found exit |
| `runcon` | ✅ Done | Medium | Run a command in a SELinux process context | `-c, --compute`: Compute process transition context before modifying
`-u, --user=USER`: Set the user component
`-r, --role=ROLE`: Set the role component
`-t, --type=TYPE`: Set the type component
`-l, --range=RANGE`: Set the range component
`CONTEXT COMMAND [ARG]...`: GNU plain-context form | Windows compatibility placeholder: accepts the GNU-shaped command line surface, validates the plain-context form's required command operand, and reports that SELinux process contexts are not supported on Windows |
| `renice` | ✅ Done | Medium | Alter priority of running processes | `-n, --priority NUM`: Specify scheduling priority
`-p, --pid PID`: Interpret argument as process ID
`-u, --user USER`: Interpret argument as username
`-g, --pgrp PGID`: Interpret argument as process group ID | Alter process priority |
| `top` | ✅ Done | High | Display Linux processes | `-b, --batch`: Batch mode
`-d, --delay=SECONDS`: Delay between updates
`-n, --iterations=NUM`: Number of iterations
`-p, --pid=PID`: Monitor specific PIDs
`-u, --user=USER`: Monitor specific user
`-c, --command`: Show command line
`-o, --field-sort=FIELD`: Sort by field (CPU, MEM, TIME, PID, NAME)
`-h, --help`: Display help
`-v, --version`: Output version information | Real-time process monitor with interactive controls |
| `watch` | ✅ Done | Medium | Execute a program periodically | `-n, --interval=SECONDS`: Seconds to wait between updates
`-d, --differences[=cumulative]`: Highlight changes between updates
`-t, --no-title`: Turn off the header
`-x, --exec`: Pass command to exec instead of sh | Periodic execution |
| `timeout` | ✅ Done | Medium | Run a command with a time limit | `-s, --signal=SIGNAL`: Send this signal on timeout
`--preserve-status`: Exit with the same status as COMMAND
`--foreground`: When not running timeout directly from a shell prompt, allow COMMAND to read from the TTY
`-k, --kill-after=DURATION`: If the command is still running after the initial timeout, send this signal | Time-limited execution; missing operand / missing command now include the GNU-style help hint and return exit `125`, parse-time invalid options also return `125` with the standard help hint, `--foreground` no longer disables timeout enforcement on Windows, invalid signal / duration / kill-after usage errors also return `125` with GNU-shaped diagnostics, verbose timeout reports prefer signal names like `TERM`, `-s0` with `-k/--kill-after` now defers the forced termination to the KILL phase and returns `137` like GNU/uutils, and child argv is now quoted with Windows `CreateProcessW` rules so spaced arguments stay single arguments |
| `vdir` | ✅ Done | Medium | List directory contents in long format by default | `OPTION... FILE...`: Forward the GNU `vdir` wrapper surface to `ls -l` | Wrapper around `ls` with long-format output as the default; forwarded argv now keeps the original option/operand order, so GNU wrapper options such as `-a` and `-d` actually reach `ls`, and single arguments containing spaces are preserved via Windows `CreateProcessW` quoting rules |
| `jobs` | ✅ Done | Medium | Display status of jobs in the current shell | `-l, --list`: List process IDs in addition to the normal information
`-n, --names`: List only jobs that have changed status since the last notification
`-p, --pid`: List only the process IDs of the job's process group leader
`-r, --running`: List only running jobs
`-s, --stopped`: List only stopped jobs | Job status display |
| `bg` | ✅ Done | Medium | Resume a job in the background | JOB_SPEC: Job specification or - for current job | Background job resume |
| `fg` | ✅ Done | Medium | Resume a job in the foreground | JOB_SPEC: Job specification or - for current job | Foreground job resume |
| `disown` | ✅ Done | Medium | Remove jobs from current shell | `-a, --all`: Remove all jobs if JOB_SPEC is not supplied
`-h, --help`: Display help
`-r, --running`: Remove only running jobs | Job removal |
| `wait` | ✅ Done | Medium | Wait for process to finish | PID: Process ID to wait for | Process wait |
| `env` | ✅ Done | Medium | Run a command in a modified environment | `-i, --ignore-environment`: Start with an empty environment
`-u, --unset=NAME`: Remove variable from the environment; repeatable
`-0, --null`: End each printed environment entry with NUL; rejected when COMMAND is present with GNU/uutils-style exit `125`
`-S, --split-string=S`: Split S into arguments using the current lightweight parser; unterminated quotes now fail with exit `125`
`-v, --debug`: Emit processing diagnostics on standard error; repeated debug flags such as `-vv` also dump raw input arguments
`-a, --argv0=STRING`: Override the child process `argv[0]` while still executing the original program
`-C, --chdir=DIR`: Change working directory before running COMMAND; GNU-style usage requires that a command be present
`NAME=VALUE`: Add or override an environment variable
`COMMAND [ARG]...`: Run COMMAND with the modified environment | Prints or executes with a materialized Windows environment block; parse-time invalid options now also return GNU/uutils-style exit `125` with the standard help hint, `-a/--argv0`, `-C/--chdir`, and `-S/--split-string` now follow last-occurrence precedence, `-0/--null` is limited to environment-printing mode and now fails with `cannot specify --null (-0) with command` when combined with a command, missing child commands now report a GNU-shaped `failed to run command 'CMD': ...` diagnostic while preserving the conventional `127` not-found exit, and full GNU `-S` parsing plus remaining GNU debug/signal details remain gaps |
| `printenv` | ✅ Done | Medium | Print all or part of environment | `-0, --null`: End each output line with NUL | Environment variable display; named empty variables still emit an empty record, mixed found/missing names keep the found output while returning status `1`, variable-name operands containing `=` are silently ignored while still causing exit status `1`, invalid options now follow GNU/uutils by returning exit `2` with the standard help hint, and full enumeration skips hidden Windows `=...` pseudo-entries |
| `export` | ✅ Done | Medium | Set an environment variable | No options | Environment variable export |
| `unset` | ✅ Done | Medium | Unset values and attributes of shell variables | No options | Variable unset |
| `logname` | ✅ Done | Low | Print user's login name | No regular options | Login name display; dispatcher-level `-V/--version` now succeeds |
| `whoami` | ✅ Done | Low | Print effective userid | No regular options | User ID display; dispatcher-level `-V/--version` now succeeds |
| `id` | ✅ Done | Medium | Print user and group information | `-a, --all`: Ignore, for compatibility with other versions
`-g, --group`: Print only the effective group ID
`-G, --groups`: Print all group IDs
`-n, --name`: Print a name instead of a number
`-r, --real`: Print the real ID instead of the effective ID
`-u, --user`: Print only the effective user ID | User and group information |
| `users` | ✅ Done | Low | Print the user names of users currently logged in | No options | Logged-in users display |
| `who` | ✅ Done | Low | Show who is logged on | `-a, --all`: Same as -b -d --login -p -r -t -T -u
`-b, --boot`: Time of last system boot
`-d, --dead`: Print dead processes
`-H, --heading`: Print line of column headings
`-l, --login`: Print system login processes
`-m`: Only hostname and user associated with stdin
`-p, --process`: Print active processes spawned by init
`-q, --count`: All login names and number of users logged on
`-r, --runlevel`: Print current runlevel
`-s, --short`: Print only name, line, and time
`-t, --time`: Print last system clock change
`-u, --users`: List users logged in | User information |
| `groups` | ✅ Done | Low | Print the groups a user is in | `--help`: Display help
`--version`: Output version information | Group information |
| `hostname` | ✅ Done | Low | Show or set the system's host name | `-a, --alias`: Alias names
`-A, --all-fqdns`: All long host names
`-d, --domain`: DNS domain name
`-f, --fqdn`: FQDN
`-i, --ip-address`: Addresses for the host name
`-I, --all-ip-addresses`: All addresses for the host
`-s, --short`: Short host name
`-y, --yp, --nis`: NIS/YP domain name | Host name display |
| `hostid` | ✅ Done | Low | Print the numeric identifier of the current host | No regular options | Host ID display; dispatcher-level `-V/--version` now succeeds |
| `uname` | ✅ Done | Medium | Print system information | `-a, --all`: Print all information
`-s, --kernel-name`: Print the kernel name
`-n, --nodename`: Print the network node hostname
`-r, --kernel-release`: Print the kernel release
`-v, --kernel-version`: Print the kernel version
`-m, --machine`: Print the machine hardware name
`-p, --processor`: Print the processor type
`-i, --hardware-platform`: Print the hardware platform
`-o, --operating-system`: Print the operating system | System information |
| `arch` | ✅ Done | Low | Print machine architecture | No regular options | Architecture display; dispatcher-level `-V/--version` now succeeds |
| `uptime` | ✅ Done | Medium | Tell how long the system has been running | `-p, --pretty`: Show uptime in pretty format
`-s, --since`: System up since
`-h, --help`: Display help
`-V, --version`: Output version information | System uptime |
| `date` | ✅ Done | Medium | Print or set system date/time | `-d, --date=STRING`: Display time described by STRING
`--debug`: Print date-parsing diagnostics
`-f, --file=DATEFILE`: Read date strings from a file
`-I, --iso-8601[=TIMESPEC]`: ISO 8601 output
`-r, --reference=FILE`: Use FILE's time
`--resolution`: Print time resolution
`-R, --rfc-email`: RFC 5322-style date output
`--rfc-3339=TIMESPEC`: RFC 3339-style output
`-s, --set=STRING`: Set the system time
`-u, --utc, --universal`: Print or set Coordinated Universal Time (UTC)
`+FORMAT`: Output format string | Date/time display and formatting |
| `cal` | ✅ Done | Low | Display a calendar | `-1, --one`: Show only the current month (default)
`-3, --three`: Show previous, current and next month
`-s, --sunday`: Sunday as first day of week
`-m, --monday`: Monday as first day of week
`-j, --julian`: Output Julian dates
`-y, --year`: Show whole current year
`-Y, --year=YEAR`: Show whole year
`-w, --week[=TYPE]`: Show week numbers | Calendar display |
| `uptime` | ✅ Done | Medium | Tell how long the system has been running | `-p, --pretty`: Show uptime in pretty format
`-s, --since`: System up since | System uptime |
| `df` | ✅ Done | Medium | Report file system disk space usage | `-h, --human-readable`: Print sizes in powers of 1024
`-H, --si`: Print sizes in powers of 1000
`-k`: Use 1K blocks
`-T, --print-type`: Print file system type
`-i, --inodes`: List inode-shaped information instead of block usage; Windows prints placeholder inode columns
File operands use the shared wildcard policy
`-t, --type=TYPE`, `-x, --exclude-type=TYPE`, `-a, --all`: tracked in the GNU parity ledger | Disk space reporting |
| `du` | ✅ Done | Medium | Estimate file space usage | `-a, --all`: Write counts for all files, not just directories
`-B, --block-size=SIZE`: Scale sizes by SIZE before printing
`-b, --bytes`: Equivalent to apparent-size with block size 1
`-c, --total`: Produce a grand total
`-d, --max-depth=N`: Print entries only if they are N or fewer levels below the command line argument
`-h, --human-readable`: Print sizes in powers of 1024
`--si`: Print sizes in powers of 1000
`-H, --dereference-args`: Accept GNU dereference-args surface on Windows
`-k`: Use 1K blocks
`-m`: Use 1M blocks
`-0, --null`: End each output record with NUL instead of newline
`-S, --separate-dirs`: Exclude subdirectory totals from each parent directory's reported size
`--time[=WORD]`: Show the latest selected timestamp for each emitted entry; supports `mtime`, `atime|access|use`, and `ctime|status`
`-X, --exclude-from=FILE`: Read exclude glob patterns from FILE
`--files0-from=FILE`: Read NUL-delimited path operands from FILE
`-s, --summarize`: Display only a total for each argument | File/directory size estimation; file operands use the shared wildcard policy, `--exclude-from` patterns feed the same matcher as `--exclude`, block counts round up, and `ctime`/`status` currently map to creation time on Windows |
| `free` | ✅ Done | Medium | Display amount of free and used memory in the system | `-b, --bytes`: Display the amount of memory in bytes
`-k, --kilo`: Display the amount of memory in kilobytes
`-m, --mega`: Display the amount of memory in megabytes
`-g, --giga`: Display the amount of memory in gigabytes
`--tera`: Display the amount of memory in terabytes
`-h, --human`: Show human-readable output
`-l, --lohi`: Show detailed low and high memory statistics | Memory usage display |
| `lsof` | ✅ Done | Medium | List open files | No options | Open file listing |
| `pwd` | ✅ Done | High | Print working directory | `-L, --logical`: Use an absolute `PWD` from the environment when it still names the current directory
`-P, --physical`: Avoid all symlinks | Working directory display; `-L` now prefers `PWD` only when it is absolute, still resolves to the current directory, and contains no `.` / `..` components, `-L/-P` follow last-occurrence precedence, the current default remains physical-mode output, and extra non-option operands now warn with GNU-shaped `ignoring non-option arguments` stderr output |
| `ps` | ✅ Done | High | Report process status | `-e, -A`: Select all processes
`-a`: Select all processes except both session leaders and processes not associated with a terminal
`-x`: Select processes without controlling ttys
`-f`: Full-format listing
`-l`: Long format
`-u USER`: Select by effective user ID or name
`-w`: Wide output
`--no-headers`: Print no header
`--sort=KEY`: Sort by column | Process listing and filtering; this is a repo-local implementation, not a GNU Coreutils manual page |
| `which` | ✅ Done | High | Locate a command in PATH | `-a, --all`: Print all matching pathnames of each argument
`--read-alias`, `--skip-alias`: Read or skip alias expansion
`--read-functions`, `--skip-functions`: Read or skip shell function expansion
`--skip-dot`: Skip directories in PATH that start with a dot
`--show-dot`: Allow directories that start with a dot to be shown
`--skip-tilde`: Skip directories in PATH that start with a tilde
`--show-tilde`: Allow directories that start with a tilde to be shown
`--tty-only`: Show matches only on a tty | Path searching with PATHEXT support, SmallVector optimization |
| `nproc` | ✅ Done | Low | Print the number of processing units available | `--all`: Print the number of installed processing units
`--ignore=N`: If possible, exclude N processing units | Processor count |
| `numfmt` | ✅ Done | Low | Convert numbers from/to human-readable strings | `-d, --delimiter=X`: Use X instead of whitespace for field delimiter
`-f, --format=FORMAT`: Use printf style floating-point FORMAT
`--from=UNIT`: Auto-scale input numbers to UNITs
`--to=UNIT`: Auto-scale output numbers to UNITs
`--round=METHOD`: Use METHOD for rounding
`--padding=N`: Pad the output to N characters | Number formatting |
| `column` | ✅ Done | Low | Columnate lists | `-c, --output-width=WIDTH`: Set output width
`-t, --table`: Determine the number of columns the table contains
`-s, --separator SEPARATOR`: Specify the possible input item delimiters
`-o, --output-separator STRING`: Specify the column separator for table output
`-x, --fillrows`: Fill rows before filling columns | Column formatting |
| `jq` | ✅ Done | Medium | Command-line JSON processor | `-c, --compact-output`: Compact instead of pretty-printed output
`-r, --raw-output`: Output raw strings
`-s, --slurp`: Read (slurp) all inputs into an array
`-R, --raw-input`: Read raw strings
`-M, --monochrome-output`: Don't colorize JSON | JSON processing |
| `tr` | ✅ Done | Medium | Translate or delete characters | `-c, -C, --complement`: Use the complement of SET1
`-d, --delete`: Delete characters in SET1
`-s, --squeeze-repeats`: Replace each sequence of a repeated character
`-t, --truncate-set1`: First truncate SET1 to length of SET2 | Character translation and deletion; operand-count diagnostics now distinguish missing `SET2`, `-d -s` missing the squeeze set, and delete-mode extra operands with GNU-style help hints |
| `mktemp` | ✅ Done | Medium | Create a temporary file or directory | `-d, --directory`: Create a directory, not a file
`-u, --dry-run`: Do not actually create anything
`-q, --quiet`: Fail silently if an error occurs
`--suffix=SUFFIX`: Append SUFFIX to TEMPLATE; SUFFIX must not contain a path separator
`-p, --tmpdir[=DIR]`: Interpret TEMPLATE relative to DIR
`-t`: Generate a template (using the temporary directory's path) | Temporary file/directory creation; explicit `--suffix=SUFFIX` now appends the suffix after template substitution, rejects suffixes containing `/` or `\` with a GNU/Microsoft-shaped diagnostic, and preserves generated paths in output when `--tmpdir` or a directory-bearing template is used |
| `mkfifo` | ✅ Done | Medium | Create named pipes (FIFOs) | `-m, --mode=MODE`: Set file permission bits
`-Z`: Set the SELinux security context to default type
`--context[=CTX]`: Set the SELinux security context
`NAME...`: FIFO names to create | Windows compatibility placeholder: validates the GNU-shaped option surface, preserves GNU-shaped `missing operand` and `File exists` diagnostics, and reports that filesystem FIFOs are not supported on Windows |
| `mknod` | ✅ Done | Medium | Create special files | `-m, --mode=MODE`: Set file permission bits
`-Z`: Set the SELinux security context to default type
`--context[=CTX]`: Set the SELinux security context
`NAME TYPE [MAJOR MINOR]`: GNU operand form; `TYPE` accepts `b`, `c`/`u`, `p` | Windows compatibility placeholder: validates GNU operand combinations such as `p` versus `b/c` major/minor rules, preserves GNU-shaped `missing operand` and `File exists` diagnostics, and reports that special files are not supported on Windows |
| `mpicalc` | ✅ Done | Low | Simple arbitrary-precision calculator | No options | Arbitrary precision calculation |
| `hmac256` | ✅ Done | Low | Compute HMAC-SHA256 | `--help`: Display help
`--version`: Output version information | HMAC computation |
| `pinky` | ✅ Done | Low | Lightweight finger | `-l`: Produce long format output
`-b`: Omit the user's home directory and shell
`-h`: Omit the user's project file
`-p`: Omit the user's plan file
`-s`: Do short format output | User information |
| `seq` | ✅ Done | Low | Print a sequence of numbers | `-f, --format=FORMAT`: Use printf style floating-point FORMAT
`-s, --separator=STRING`: Use STRING to separate numbers
`-t, --terminator=STRING`: Use STRING instead of the final newline
`-w, --equal-width`: Equalize width by padding with leading zeroes | Sequence generation; missing and extra operands now include GNU-style help hints, `-t/--terminator` now replaces only the final output separator while leaving intermediate separators unchanged, and `-w` now rejects an explicit `-f/--format` string with the GNU/uutils-style conflict diagnostic |
| `sleep` | ✅ Done | Low | Delay for a specified time | `NUMBER[SUFFIX]`: Pause for NUMBER seconds | Sleep delay; missing operands now include the GNU-style help hint, malformed or negative durations now use GNU-shaped `invalid time interval` diagnostics, multiple invalid duration operands are now all reported before the final help hint, leading whitespace remains accepted, and trailing whitespace is now rejected like GNU/uutils |
| `yes` | ✅ Done | Low | Output a string repeatedly | `STRING...`: Strings to join with spaces before repeating | Repeated output; GNU/uutils-style multi-operand invocations now join all operands with single spaces instead of using only the first operand, and `-V/--version` now succeeds instead of being misparsed as an unknown option |
### System Utilities
| Command | Status | Priority | Description | Parameters/Options | Implementation Notes |
|---------|--------|----------|-------------|-------------------|---------------------|
| `help` | ✅ Done | High | Display help information about commands | `COMMAND`: Display help for specific command | Uses command metadata for help generation |
| `man` | ✅ Done | Low | Display manual pages | `COMMAND`: Display the manual page for a command | Repo-local manual lookup with `.exe` handling |
| `exit` | ✅ Done | High | Exit the shell | No options | Simple exit call with pipeline structure |
| `clear` | ✅ Done | High | Clear the terminal screen | No options | Uses system call to clear screen |
| `cd` | ✅ Done | High | Change the current directory | `-L, --logical`: Force symbolic links to be followed
`-P, --physical`: Use the physical directory structure without following symbolic links | Uses SetCurrentDirectory API with pipeline structure |
| `type` | ❌ TODO | Medium | Describe command type | `COMMAND`: Describe specific command | Not yet implemented |
| `alias` | ❌ TODO | Low | Create an alias for a command | `NAME=VALUE`: Define an alias
`-p`: Print all defined aliases | Not yet implemented |
## Implementation Guidelines
### General Structure
Each command should follow this general structure:
1. **Module Declaration**: Start with `export module cmd.;`
2. **Imports**: Import necessary modules (`import core;`, `import utils;`, etc.)
3. **Constants Namespace**: Define command-specific constants
4. **Option Definitions**: Define command options using the `OPTION` macro
5. **Pipeline Components**: Implement pipeline components for command processing
6. **Command Implementation**: Implement the main command logic
7. **Registration**: Register the command using `REGISTER_COMMAND` macro
### Example Structure
```cpp
export module cmd.echo;
import core;
import utils;
using cmd::meta::OptionMeta;
using cmd::meta::OptionType;
namespace echo_constants {
// Command-specific constants
}
// Define options
export auto constexpr ECHO_OPTIONS =
std::array{
OPTION("-n", "--no-newline", "do not output the trailing newline"),
OPTION("-e", "--escape", "enable interpretation of backslash escapes"),
};
namespace echo_pipeline {
namespace cp = core::pipeline;
// Validate arguments
auto validate_arguments(std::span args) -> cp::Result> {
std::vector validated_args;
for (auto arg : args) {
validated_args.push_back(std::string(arg));
}
return validated_args;
}
// Build text from arguments
auto build_text(const std::vector& args) -> std::string {
std::string text;
for (size_t i = 0; i < args.size(); ++i) {
text += args[i];
if (i < args.size() - 1) {
text += " ";
}
}
return text;
}
// Handle escape sequences
auto to_uppercase(std::string text) -> std::string {
std::ranges::transform(text, text.begin(), ::toupper);
return text;
}
// Process command
template
auto process_command(const CommandContext& ctx)
-> cp::Result
{
auto args_result = validate_arguments(ctx.positionals);
if (!args_result) {
return args_result.error();
}
auto args = *args_result;
return build_text(args);
}
}
REGISTER_COMMAND(echo,
/* name */
"echo",
/* synopsis */
"echo [SHORT-OPTION]... [STRING]...",
/* description */
"Display a line of text.",
/* examples */
" echo Hello World Display 'Hello World'\n"
" echo -n Hello Display 'Hello' without trailing newline\n"
" echo -e Hello\\nWorld Display 'Hello' and 'World' on separate lines",
/* see_also */
"cat, printf",
/* author */
"WinuxCmd Team",
/* copyright */
"Copyright © 2026 WinuxCmd",
/* options */
ECHO_OPTIONS
) {
using namespace echo_pipeline;
auto result = process_command(ctx);
if (!result) {
cp::report_error(result, L"echo");
return 1;
}
auto text = *result;
// Get options
bool no_newline = ctx.get("--no-newline", false);
bool escape = ctx.get("--escape", false);
// Handle escape sequences if enabled
if (escape) {
// Implement escape sequence handling
}
// Output result
std::cout << text;
if (!no_newline) {
std::cout << std::endl;
}
return 0;
}
```
### Best Practices
1. **Pipeline Architecture**: Use pipeline components for modular processing
2. **Type Safety**: Use `CommandContext` for type-safe option access
3. **Error Handling**: Use `core::pipeline::Result` for consistent error handling
4. **Documentation**: Provide clear documentation for each command
5. **Testing**: Test commands with various inputs and options
6. **Performance**: Optimize for performance where appropriate
7. **Compatibility**: Follow POSIX standards where possible
### Testing
Each command should be tested with:
1. **Basic functionality**: Test the command with no options
2. **All options**: Test each option individually
3. **Combined options**: Test multiple options together
4. **Edge cases**: Test with empty inputs, large inputs, etc.
5. **Error cases**: Test with invalid inputs and options
## Migration Guide
### From Legacy Implementation
To migrate a command from the legacy implementation to the new pipeline-based structure:
1. **Update module declaration**: Use `export module cmd.;`
2. **Add imports**: Add necessary imports (`import core;`, `import utils;`)
3. **Define options**: Use the `OPTION` macro to define options
4. **Create pipeline namespace**: Implement pipeline components
5. **Update command implementation**: Use `CommandContext` for option access
6. **Register command**: Use the new `REGISTER_COMMAND` macro
### Example Migration
#### After (Pipeline-Based Architecture)
```cpp
export module cmd.echo;
import core;
import utils;
using cmd::meta::OptionMeta;
using cmd::meta::OptionType;
namespace echo_constants {
// Command-specific constants can be defined here
}
// Define options
export auto constexpr ECHO_OPTIONS =
std::array{
OPTION("-n", "--no-newline", "do not output the trailing newline"),
OPTION("-e", "--escape", "enable interpretation of backslash escapes"),
};
namespace echo_pipeline {
namespace cp = core::pipeline;
// Validate arguments
auto validate_arguments(std::span args) -> cp::Result> {
std::vector validated_args;
for (auto arg : args) {
validated_args.push_back(std::string(arg));
}
return validated_args;
}
// Build text from arguments
auto build_text(const std::vector& args) -> std::string {
std::string text;
for (size_t i = 0; i < args.size(); ++i) {
text += args[i];
if (i < args.size() - 1) {
text += " ";
}
}
return text;
}
// Process command
template
auto process_command(const CommandContext& ctx)
-> cp::Result
{
auto args_result = validate_arguments(ctx.positionals);
if (!args_result) {
return args_result.error();
}
auto args = *args_result;
return build_text(args);
}
}
REGISTER_COMMAND(echo,
/* name */
"echo",
/* synopsis */
"echo [SHORT-OPTION]... [STRING]...",
/* description */
"Display a line of text.",
/* examples */
" echo Hello World Display 'Hello World'\n"
" echo -n Hello Display 'Hello' without trailing newline\n"
" echo -e Hello\\nWorld Display 'Hello' and 'World' on separate lines",
/* see_also */
"cat, printf",
/* author */
"WinuxCmd Team",
/* copyright */
"Copyright © 2026 WinuxCmd",
/* options */
ECHO_OPTIONS
) {
using namespace echo_pipeline;
auto result = process_command(ctx);
if (!result) {
cp::report_error(result, L"echo");
return 1;
}
auto text = *result;
// Get options using CommandContext
bool no_newline = ctx.get("--no-newline", false);
bool escape = ctx.get("--escape", false);
// Handle escape sequences if enabled
if (escape) {
// Implement escape sequence handling
}
// Output result
std::cout << text;
if (!no_newline) {
std::cout << std::endl;
}
return 0;
}
```
## Reference Implementation
The `echo.cppm` file serves as the reference implementation for the new pipeline-based architecture. It demonstrates:
1. **Pipeline Components**: Separate validation and processing logic
2. **Option Handling**: Use of `CommandContext` for type-safe option access
3. **Error Handling**: Use of `core::pipeline::Result` for error reporting
4. **Command Registration**: Proper use of `REGISTER_COMMAND` macro
All new commands should follow this pattern for consistency and maintainability.