# 命令实现状态
本文档跟踪 WinuxCmd 项目中命令的实现状态,该项目现在使用基于管道的架构进行命令处理。
## 分类
### 文件管理
| 命令 | 状态 | 优先级 | 描述 | 参数选项 | 实现说明 |
|------|------|--------|------|----------|----------|
| `ls` | ✅ 已实现 | 高 | 列出目录内容 | `-a, --all`: 不忽略以 . 开头的条目
`-A, --almost-all`: 不列出隐含的 . 和 ..
`-b, --escape`: 用 C 风格转义显示不可打印字符
`-d, --directory`: 列出目录本身而不是目录内容
`-f`: 按目录顺序列出所有条目
`-F, --classify`: 为条目追加类型指示符
`--file-type`: 追加类型指示符,但不为可执行文件加 `*`
`-I, --ignore=PATTERN`: 忽略匹配 PATTERN 的条目
`--hide=PATTERN`: 隐藏匹配 PATTERN 的条目,`-a` 或 `-A` 时失效
`-l, --long, --long-list`: 使用长列表格式
`--full-time`: 等价于 `-l --time-style=full-iso`
`--author`: 在长列表中显示 author 列
`-h, --human-readable`: 与 -l 一起使用,以人类可读格式打印大小
`-r, --reverse`: 反转排序顺序
`-t`: 按修改时间排序
`-U`: 不排序,按目录顺序列出
`-v`: 对文本中的版本号进行自然排序
`-X, --sort=WORD`: 按指定键排序,例如 `extension`
`-n, --numeric-uid-gid`: 类似 -l,但列出数字用户和组 ID
`-g`: 类似 -l,但不列出所有者
`-o`: 类似 -l,但不列出组信息
`-1`: 每行列出一个文件
`-C`: 按列列出条目
`-w, --width`: 将输出宽度设置为 COLS
`--indicator-style=WORD`: 选择 slash/file-type/classify/none 后缀样式
`--color`: 彩色化输出 | 使用管道架构实现,支持彩色输出,SmallVector 优化,并且现在在同一调用里有 sibling operand 失败时仍会为剩余目录或 junction 保留 GNU 风格的目录头,同时会把缺失路径的 `cannot access` 诊断输出到 stderr,并返回 GNU 风格的退出码 `2`,并且在长格式下会把 `-F/--classify/--file-type` 的 indicator 挂在 symlink/junction 名字本身而不是显示出来的 target 上,同时会把 Windows 目录 junction 的长列表 size 维持为 `0`,而不再复用显示出来的目标路径长度,并且显示 junction target 时会去掉原始 Windows namespace 前缀,如 `\??\` / `\\?\`;现在也接受带尾分隔符的命令行目录/junction operand,例如 `dir/` 或 `junc/`,同时继续保留用户原始拼写;在长格式彩色输出里,link 名和显示出来的 target 现在也会分开着色,而不再把整个 `name -> target` 都刷成一种 link 颜色;现在也接受 GNU 的 `--long` 作为 `-l` 的直接别名;同时也接受单数和复数两种 `--dereference-command-line-symlink(s)-to-dir` 长选项写法;同时也补齐了 GNU 的 `--full-time` 语义,把它接成 `-l --time-style=full-iso`,但后续更晚出现的格式或时间样式选项仍然可以覆盖它;现在也会把 GNU 的 `-g`、`-n`、`-o` 当作和 `-l` 一样的长列表请求来处理,但如果后面又显式给了别的格式选项,仍然按最后一次出现生效;现在也会真的按 GNU 语义裁掉 `-g`、`-o`、`--no-group` 对应的 owner/group 列;`--hide=PATTERN` 现在也会按 GNU/Microsoft 的常见行为只在默认模式下隐藏匹配项,而在 `-a` / `-A` 下被覆盖,同时 `--ignore=PATTERN` 在 all-mode 里仍会继续过滤;GNU `--author` 现在也会被接受,并在 long format 下额外输出一列 author;在 Windows 上这列按 Microsoft/Coreutils 的近似做法复用 owner 名称;并且现在也会按 Microsoft Coreutils 在 Windows 下的近似规则显示权限串:可写条目映射为 `rwxrwxrwx`,只读条目映射为 `r-xr-xr-x`;长格式 `.` / `..` 现在也会重新读取真实目录元数据,因此父目录 size 与 `total` 不再塌成零;`ls -laL DIRLINK` 这类解引用后的目录 symlink / junction 内容视图现在也会把 synthetic `.` 条目保持在目标目录视图上,而不是又显示回 link;默认 `-s` 输出和目录 `total` 头现在也会按更接近 Windows/Coreutils 的分配字节口径统计,而不是先按 1K block 预除;在 Windows 下,`--block-size=SIZE` / `-k` 现在只会缩放长格式 size 列,`-s` 与目录 `total` 仍保持这套字节口径,除非显式启用 `-h` 或 `--si`;长格式里的链接 target 现在也会跟随 C/shell/escape quoting 规则一起显示,而不再把 target 路径裸着输出 |
| `cat` | ✅ 已实现 | 高 | 连接文件并打印到标准输出 | `-A, --show-all`: 等同于 `-vET`
`-b, --number-nonblank`: 仅对非空输出行编号
`-e`: 等同于 `-vE`
`-E, --show-ends`: 在每行末尾显示 $
`-n, --number`: 对所有输出行编号
`-s, --squeeze-blank`: 压缩多个相邻空行
`-t`: 等同于 `-vT`
`-T, --show-tabs`: 将 TAB 字符显示为 ^I
`-u`: GNU 兼容占位,当前忽略
`-v, --show-nonprinting`: 显示不可打印字符 | 简单文件读写,带有管道结构,SmallVector 优化 |
| `cp` | ✅ 已实现 | 高 | 复制文件和目录 | `-a, --archive`: 递归复制并保留 Windows 时间戳/属性
`-p`: 保留 Windows 时间戳/属性
`-i, --interactive`: 覆盖前提示
`-r, -R, --recursive`: 递归复制目录
`-t, --target-directory`: 将所有 SOURCE 复制到 DIRECTORY
`-T, --no-target-directory`: 将 DEST 当作普通文件
`--strip-trailing-slashes`: 在查找前剥掉每个源操作数尾部的 `/` 或 `\`
`-n, --no-clobber`: 不覆盖已有文件
`-u, --update`: 仅当 SOURCE 更新时复制
`-v, --verbose`: 解释正在执行的操作
`-f, --force`: 强制复制而不提示 | 文件系统操作,带有错误处理;owner/mode 保留是 Windows 近似,并已支持 GNU 风格的源参数尾斜杠剥离 |
| `mv` | ✅ 已实现 | 高 | 移动(重命名)文件 | `-i, --interactive`: 覆盖前提示
`-I`: 批量移动前提示一次
`-v, --verbose`: 解释正在执行的操作
`-f, --force`: 覆盖前不提示
`-n, --no-clobber`: 不覆盖现有文件
`--interactive[=WHEN]`: GNU 风格覆盖提示模式,按最后一次出现生效 | 文件系统操作,带有错误处理,SmallVector 优化 |
| `rm` | ✅ 已实现 | 高 | 删除文件或目录 | `-f, --force`: 忽略不存在的文件和参数,从不提示
`-i, --interactive`: 每次删除前提示
`-r, -R, --recursive`: 递归删除目录及其内容
`-v, --verbose`: 解释正在执行的操作 | 文件系统操作,带有错误处理;缺失 operand 现在也会输出 GNU 风格的 `Try 'rm --help' for more information.` 提示 |
| `mkdir` | ✅ 已实现 | 高 | 创建目录 | `-p, --parents`: 不存在时无错误,必要时创建父目录
`-v, --verbose`: 为创建的每个目录打印一条消息
`-m, --mode`: 设置文件模式(如 chmod) | 文件系统操作,带有错误处理;缺少 operand 时现在会附带 GNU 风格 help hint |
| `rmdir` | ✅ 已实现 | 中 | 删除空目录 | `--ignore-fail-on-non-empty`: 忽略删除非空目录的每次失败
`-p, --parents`: 删除目录及其祖先
`-v, --verbose`: 为删除的每个目录打印一条消息 | 文件系统操作,带有错误处理;缺少 operand 时现在会附带 GNU 风格 help hint,把普通文件误传给 `rmdir` 时现在会输出更接近 GNU 的 `Not a directory` 诊断,`-v` 现在也会在每次尝试删除前输出 GNU/uutils 形状的 `removing directory, 'DIR'` 提示行,包括失败的尝试,而且 `-p` 在祖先目录因非空而停止清理时现在也会正确返回失败 |
| `touch` | ✅ 已实现 | 中 | 更改文件时间戳或创建空文件 | `-a`: 仅更改访问时间
`-m`: 仅更改修改时间
`-c, --no-create`: 不创建任何文件
`-d, --date`: 解析字符串并使用它代替当前时间
`-r, --reference`: 使用此文件的时间代替当前时间
`-t, --time`: 使用指定时间而不是当前时间
`-h, --no-dereference`: 影响每个符号链接而不是任何引用的文件
`--time=WORD`: 选择要更改的时间类型 | 文件系统操作,带有错误处理 |
| `ln` | ✅ 已实现 | 中 | 在文件之间创建链接 | `-s, --symbolic`: 创建符号链接而不是硬链接
`-f, --force`: 删除现有目标文件
`-i, --interactive`: 提示是否删除目标
`-v, --verbose`: 打印每个链接文件的名称
`-n, --no-dereference`: 如果 LINK_NAME 是指向目录的符号链接,则将其视为普通文件
`-t, --target-directory=DIRECTORY`: 在 DIRECTORY 中创建链接
`-T, --no-target-directory`: 总是把 LINK_NAME 当普通目标路径处理 | 文件链接(硬/符号);`ln TARGET` 现在会在当前目录按 `basename(TARGET)` 创建链接,`ln SOURCE DIR` 现在也会在第二个 operand 已存在且是目录时把它当目标目录,除非显式启用 `-T`,缺失源文件失败、目标已存在失败以及强制覆盖时的删除失败现在都会输出 GNU 形状文案,而不是 Win32 数字码/本地 `exists` 文案,多 operand 调用按 GNU 的 `TARGET... DIRECTORY` 语义处理,不再把一个 source 直接配多个 target,且 `-t` / `-T` 会显式冲突 |
| `diff` | ✅ 已实现 | 中 | 逐行比较文件 | `-u, --unified=NUM`: 输出 NUM(默认 3)行统一上下文
`-q, --brief`: 仅输出文件是否不同
`-i, --ignore-case`: 忽略文件内容中的大小写差异
`-w, --ignore-all-space`: 忽略所有空白
`-B, --ignore-blank-lines`: 忽略所有行均为空白的更改
`-y, --side-by-side`: 以两列输出
`-r, --recursive`: 递归比较任何子目录 [未支持] | 文件比较;文件参数走统一通配符策略,并且必须最终解析成恰好两个文件,多余 operand 现在会附带 GNU 风格 help hint |
| `file` | ✅ 已实现 | 中 | 确定文件类型 | `-b, --brief`: 不在输出行前添加文件名
`-i, --mime`: 输出 mime 类型字符串
`-z, --compress`: 尝试查看压缩文件内部
`--mime-type`: 仅输出 MIME 类型
`--mime-encoding`: 仅输出 MIME 编码 | 文件类型检测 |
| `cksum` | ✅ 已实现 | 低 | CRC 校验和和字节计数 | `-a, --algorithm=TYPE`: 选择 `sysv`、`bsd` 或 `crc`
`-c, --check=FILE`: 从 FILE 读取并校验 checksum
`--ignore-missing`: 校验时跳过缺失的目标文件
`-q, --quiet`: 校验模式下隐藏成功的 `OK` 行
`-s, --status`: 校验模式下静默正常输出,仅通过退出码表达结果
`-w, --warn`: 报告 malformed checksum line 及其位置
`--strict`: 当存在 malformed checksum line 时失败
`--tag`: 输出 BSD 风格 tagged 结果
`--untagged`: 强制未标记输出
`-z, --zero`: 以 NUL 结束输出记录
`--raw`: 输出原始 digest 字节
`--base64`: 输出 base64 digest 字节
`-l, --length=BITS`: 在支持时选择 digest 长度
`--debug`: 打印调试输出 | 校验和计算;校验模式现在会验证未标记记录里的大小字段,支持 GNU 风格的 `--quiet` / `--status`,并把 malformed 校验行处理收敛到 `--warn` / `--strict` 语义 |
| `base64` | ✅ 已实现 | 低 | Base64 编码/解码数据 | `-d, --decode`: 解码数据
`-i, --ignore-garbage`: 解码时忽略非字母表字符
`-w, --wrap=COLS`: 在 COLS 字符后折行 | Base64 编码/解码;多余文件参数现在会按 GNU 风格输出 `extra operand 'FILE'`,并附带标准的 `Try 'base64 --help' for more information.` 提示 |
| `base32` | ✅ 已实现 | 低 | Base32 编码/解码数据 | `-d, --decode`: 解码数据
`-w, --wrap=COLS`: 在 COLS 字符后折行 | Base32 编码/解码;多余文件参数现在会按 GNU 风格输出 `extra operand 'FILE'`,并附带标准的 `Try 'base32 --help' for more information.` 提示 |
| `basenc` | ✅ 已实现 | 低 | 使用多种编码算法进行编解码 | `-d, --decode`: 解码数据
`-i, --ignore-garbage`: 解码时忽略非字母表字符
`-w, --wrap=COLS`: 在 COLS 字符后折行
`--base64`、`--base32`、`--base16`、`--base64url`、`--base32hex`、`--base2msbf`、`--base2lsbf`、`--z85`: 选择编码 | 多种编码/解码;多余文件参数现在会按 GNU 风格输出 `extra operand 'FILE'`,并附带标准的 `Try 'basenc --help' for more information.` 提示 |
| `dd` | ✅ 已实现 | 中 | 转换并复制文件 | `if=FILE`: 从 FILE 读取而不是 stdin
`of=FILE`: 写入 FILE 而不是 stdout
`bs=BYTES`: 同时设置输入和输出块大小
`ibs=BYTES`: 设置输入块大小
`obs=BYTES`: 设置输出块大小
`cbs=BYTES`: 转换块大小 [已解析]
`count=N`: 只复制 N 个输入块
`skip=N`: 跳过 N 个 ibs 大小的输入块
`seek=N`: 跳过 N 个 obs 大小的输出块
`conv=CONVS`: 支持 `notrunc` 和 `sync`;`noerror` 仍是占位
`status=none|noxfer|progress`: 控制诊断输出 | 文件转换与复制 |
| `sum` | ✅ 已实现 | 低 | 打印校验和和块计数 | `-r`: 使用 BSD 格式校验和
`-s`: 使用 System V 格式校验和 | 旧式校验和兼容 |
| `expr` | ✅ 已实现 | 中 | 计算表达式 | `EXPRESSION`: 要求值的表达式 | 表达式求值 |
| `factor` | ✅ 已实现 | 低 | 打印质因数 | 无选项 | 质因数分解 |
| `realpath` | ✅ 已实现 | 低 | 打印解析的绝对路径 | `-e, --canonicalize-existing`: 路径的所有组件必须存在
`-E, --canonicalize`: 除最后一个外其余路径组件必须存在
`-m, --canonicalize-missing`: 不需要任何路径组件存在
`-L, --logical`: 已接收,使用 Windows 路径规范化
`-P, --physical`: 已接收,使用 Windows 路径规范化
`-q, --quiet`: 抑制错误消息
`-s, --strip, --no-symlinks`: 不展开符号链接
`--relative-to=DIR`: 输出相对 DIR 的解析路径
`--relative-base=DIR`: 仅对 DIR 之下的路径输出相对形式
`-z, --zero`: 每个输出行以 NUL 结束
GNU 风格 operand 诊断:missing operand help hint,与 invalid empty string 拒绝 | 路径解析;现在要求至少提供一个 path operand,`-e`、`-E`、`-m` 按最后一次出现生效,空 path/relative operand 会按 invalid empty string 拒绝,且 `-e` 下 `--relative-to` / `--relative-base` 现在要求解析后是目录,GNU `-L` 与 `-P` 的完整 symlink 顺序仍是 partial |
| `find` | ✅ 已实现 | 高 | 搜索目录层次结构中的文件 | `-name PATTERN`: 基名匹配 shell 模式 PATTERN
`-iname PATTERN`: 基名匹配 shell 模式 PATTERN,忽略大小写
`-path PATTERN`: 完整路径匹配 shell 模式 PATTERN
`-ipath PATTERN`: 完整路径匹配 shell 模式 PATTERN,忽略大小写
`-type X`: 文件类型为 X(当前支持 f/d/l)
`-size N`: 文件大小匹配 N 个单位;支持 `+N/-N/N` 与 `c/k/M/G` 单位
`-empty`: 文件或目录为空
`-mtime N`: 文件内容最后修改距今 N*24 小时
`-mmin N`: 文件内容最后修改距今 N 分钟
`-mindepth N`: 至少从 N 层目录之后开始测试
`-maxdepth N`: 最多搜索到 N 层深度
`-print`: 输出完整路径
`-print0`: 输出完整路径并以 NUL 结尾
`-printf FORMAT`: 输出 GNU 风格文件字段(`%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@`,以及零填充本地时间组件子集 `%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}`、`%%`)和常用转义,包括 GNU 风格 `\c` 与八进制 `\NNN`
`-prune`: 跳过当前遍历中的目录下探
`-quit`: 立即停止搜索
`-L`: 遍历时跟随符号链接
`-H`: 只跟随命令行根参数上的符号链接;遍历时遇到的符号链接仍需 `-L`
`-delete`: 使用深度优先遍历删除匹配文件/目录
`-exec COMMAND {} ;`: 每个匹配项执行一次并替换 `{}`
`-exec COMMAND {} +`: 批量把匹配路径追加到 COMMAND 末尾
`-ok COMMAND {} ;`: 每个匹配项确认后执行
`-ok COMMAND {} +`: 批量执行前确认一次 | 文件搜索;表达式优先级和短路行为已按 GNU 常见语义收敛,当前目录 root 下默认 `-print` / `-print0` 输出现在会使用更接近 Microsoft 的 `.\` 前缀,同时保持后续相对路径部分稳定,junction 风格目录 reparse point 也会在 `-type l` 和相关 `-printf` 字段里按 link-like 条目处理,`%S` 现在会以 Win32 allocated size 与 logical size 的比值作为本地最接近的 sparseness 近似,而 `%A/%B/%C/%T` 的时间组件子集现在也提供了 `@` 形式之外一组稳定的本地时间表面,但更深的 GNU regex 与 `-printf` 细节仍有缺口 |
### 文本处理
| 命令 | 状态 | 优先级 | 描述 | 参数选项 | 实现说明 |
|------|------|--------|------|----------|----------|
| `echo` | ✅ 已实现 | 高 | 显示一行文本 | `-n`: 不输出尾随换行符
`-e`: 启用反斜杠转义的解释
`-E`: 显式禁止反斜杠转义的解释
`-u, --upper`: 将文本转换为大写
`-r, --repeat N`: 重复输出 N 次 | 使用管道架构实现,作为参考实现,支持包括 `\n`、`\t`、`\xHH`、`\uHHHH` 在内的转义序列,也支持 GNU 旧式八进制转义如 `\43`、`\101`,裸 `echo` 现在也会按 GNU/uutils 语义成功输出单独一个换行,而不是把空参数当错误,`-e` / `-E` 也已改成 GNU/uutils 风格的“最后一次出现生效”,像 `\ `、缺少十六进制数字的 `\x` 这类未知或不完整转义现在也会像 GNU/uutils 一样保留前导反斜杠,`\xFF` 这类非 UTF-8 字节和 `\xf0\x9f\x98\x82` 这类 UTF-8 字节序列现在也有测试覆盖,同时 `POSIXLY_CORRECT` 下也会默认启用转义处理、继续保留 `-n`、忽略 `-E` 的关闭作用,并把 `--help`、`--version`、`-nE` 这类非前导单独 `-n` 的“像选项的参数”当普通文本输出 |
| `grep` | ✅ 已实现 | 高 | 打印匹配模式的行 | `-E, --extended-regexp`: 将模式解释为扩展正则表达式
`-F, --fixed-strings`: 将模式解释为固定字符串
`-G, --basic-regexp`: 将模式解释为基本正则表达式
`-e, --regexp=PATTERNS`: 指定匹配模式,可重复
`-f, --file=FILE`: 从文件读取模式,可重复
`-i, --ignore-case`: 忽略大小写区别
`-w, --word-regexp`: 只匹配完整单词
`-x, --line-regexp`: 只匹配整行
`-z, --null-data`: 使用 NUL 分隔记录
`-v, --invert-match`: 反转匹配的含义
`-m, --max-count=NUM`: 选中 NUM 行后停止
`-b, --byte-offset`: 输出字节偏移
`-n, --line-number`: 用 1 基行号为每行输出添加前缀
`-H, --with-filename`: 输出文件名前缀
`-h, --no-filename`: 不输出文件名前缀
`-o, --only-matching`: 只输出匹配片段
`-q, --quiet`: 不输出常规结果
`-r, --recursive`: 递归搜索目录
`-R, --dereference-recursive`: 递归并跟随目录符号链接
`--include=GLOB`、`--exclude=GLOB`、`--exclude-from=FILE`、`--exclude-dir=GLOB`: 过滤搜索文件
`-A/-B/-C`: 输出上下文
`--group-separator=SEP`、`--no-group-separator`: 控制上下文组分隔符
`--binary-files=TYPE`、`-a`、`-I`: 二进制文件策略
`-D, --devices=ACTION`: 对设备/FIFO/socket 使用 `read` 或 `skip` 策略
`--color`: 使用标记高亮匹配项 | 支持正则表达式的模式匹配,文件参数支持通配符展开,支持可重复参数存储,SmallVector 优化 |
| `sort` | ✅ 已实现 | 中 | 对文本文件的行进行排序 | `-b, --ignore-leading-blanks`: 忽略前导空格
`-d, --dictionary-order`: 仅按空白和字母数字比较
`-f, --ignore-case`: 将小写字符折叠为大写字符
`-g, --general-numeric-sort`: 按通用数值比较
`-h, --human-numeric-sort`: 按人类可读数值比较
`-i, --ignore-nonprinting`: 忽略不可打印字符
`-k, --key`: 可重复键排序,支持 `F[.C][OPTS][,F[.C][OPTS]]` 范围
`-M, --month-sort`: 按月份名称排序
`-n, --numeric-sort`: 根据字符串数值进行比较
`-r, --reverse`: 反转比较结果
`-R, --random-sort`: 随机排序
`--random-source=FILE`: 从 FILE 读取确定性随机源
`-S, --buffer-size=SIZE`: 接受 GNU SIZE 形式作为内存提示
`--parallel=N`: 接受带校验的并发 hint
`--batch-size=N`: 接受带校验的 merge hint
`--compress-program=PROG`: 接受带校验的非空压缩 hint
`-T, --temporary-directory=DIR`: 接受“必须已存在目录”的临时目录 hint
`-s, --stable`: 稳定排序
`-u, --unique`: 使用 -c 时检查严格排序
`-C, --check-silent`: 静默检查输入是否已排序
`-t, --field-separator`: 使用 SEP 代替从非空白到空白的转换
`-z, --zero-terminated`: 行定界符是 NUL,而不是换行符
`-o FILE`: 将结果写入 FILE 而不是标准输出 | 支持有序多键、键范围、字符位置、常见每键修饰符、GNU 风格静默检查模式,以及当前仍不改变单线程 merge / temp-file 实现的 `--parallel` / `--batch-size` / `--compress-program` / `-T` hint |
| `tsort` | ✅ 已实现 | 低 | 执行拓扑排序 | 无选项 | 成对输入的拓扑排序 |
| `wc` | ✅ 已实现 | 中 | 为每个文件打印换行符、单词和字节计数 | `-c, --bytes`: 打印字节计数
`-l, --lines`: 打印换行符计数
`-w, --words`: 打印单词计数
`-m, --chars`: 打印字符计数
`-L, --max-line-length`: 打印最大显示宽度
`--files0-from=FILE`: 从 NUL 分隔列表读取文件名
`--total=WHEN`: 控制总计输出方式 | 带有多种模式的字符计数,SmallVector 优化 |
| `head` | ✅ 已实现 | 低 | 输出文件的前几部分 | `-c, --bytes=[-]NUM`: 打印前 N 个字节,可用负值表示从末尾回退
`-n, --lines=[-]NUM`: 打印前 N 行,可用负值表示从末尾回退
`-q, --quiet, --silent`: 从不打印给出文件名的头
`-v, --verbose`: 始终打印给出文件名的头
`-z, --zero-terminated`: 行定界符是 NUL,而不是换行符 | 文件头部提取,支持字节/行选项,SmallVector 优化 |
| `tail` | ✅ 已实现 | 低 | 输出文件的最后部分 | `-c, --bytes=[+]NUM`: 输出最后 N 个字节,可用正值表示从头开始偏移
`-n, --lines=[+]NUM`: 输出最后 N 行,可用正值表示从头开始偏移
`-q, --quiet, --silent`: 从不打印给出文件名的头
`-v, --verbose`: 始终打印给出文件名的头
`-z, --zero-terminated`: 行定界符是 NUL,而不是换行符
`-f, --follow`: 随着文件增长输出附加数据
`--follow=name`: 按文件名而不是描述符跟踪
`-F`: 等同于 `--follow=name --retry`
`-s, --sleep-interval=SECONDS`: 跟踪时两轮之间暂停
`--pid=PID`: 在 PID 退出后停止跟踪
`--retry`: 持续尝试打开不可访问的文件
`--use-polling`: 显式选择 polling 跟踪模式
`--max-unchanged-stats=N`: 名称跟踪时 N 轮未变化后重新打开检查 | 文件尾部提取,支持按名称跟踪;`-F` / `--follow=descriptor|name` 选项族现在按最后一次出现生效,`--use-polling` 会映射到当前基于 polling 的跟踪实现 |
| `sed` | ✅ 已实现 | 中 | 用于过滤和转换文本的流编辑器 | `-e, --expression`: 将 SCRIPT 添加到要执行的命令;可重复,并与 `-f` 保持顺序
`-f, --file`: 将 SCRIPT-FILE 的内容添加到命令;可重复,并与 `-e` 保持顺序
`-n, --quiet, --silent`: 禁止模式空间的自动打印
`-i, --in-place`: 就地编辑文件 | 支持按顺序执行的可重复脚本参数,SmallVector 优化 |
| `uniq` | ✅ 已实现 | 中 | 报告或省略重复行 | `-c, --count`: 在行前加上出现次数作为前缀
`-d, --repeated`: 仅打印重复行,每组一个
`-D, --all-repeated[=METHOD]`: 打印每组的所有重复行
`-f, --skip-fields`: 避免比较前 N 个字段
`-i, --ignore-case`: 比较时忽略大小写差异
`-s, --skip-chars`: 避免比较前 N 个字符
`--group[=METHOD]`: 以组为单位输出重复项
`-u, --unique`: 仅打印唯一行
`-w, --check-chars`: 比较行中不超过 N 个字符
`-z, --zero-terminated`: 行定界符是 NUL,而不是换行符 | 重复行检测和过滤,SmallVector 优化;分组模式已接入,GNU 分隔符细节仍需打磨 |
| `cut` | ✅ 已实现 | 中 | 从文件的每一行中移除部分 | `-b, --bytes`: 按字节切割
`-c, --characters`: 按字符切割
`-d, --delimiter`: 使用 DELIM 而不是 TAB 作为字段定界符
`-w`: 使用连续空格或 Tab 作为字段定界符(Microsoft/FreeBSD 扩展)
`-f, --fields`: 仅选择这些字段
`--complement`: 选择指定字节、字符或字段集合的补集
`--output-delimiter=STRING`: 在选中字段或字节/字符范围之间使用 STRING
`-s, --only-delimited`: 不打印不包含定界符的行
`-z, --zero-terminated`: 行定界符是 NUL,而不是换行符 | 字段、字节和字符提取;`-w` 现在会按微软实现处理空白字段拆分、TAB 输出和 `-d` 冲突 |
| `tee` | ✅ 已实现 | 中 | 从标准输入读取并写入标准输出和文件 | `-a, --append`: 追加到给定的文件,不覆盖
`-i, --ignore-interrupts`: 忽略中断信号
`-p, --diagnose`: 将错误写入标准错误 | 标准输入/输出重定向,SmallVector 优化 |
| `xargs` | ✅ 已实现 | 高 | 从输入构建并执行命令行 | `-n, --max-args=MAX-ARGS`: 每个命令行最多使用 MAX-ARGS 个参数
`-L, --max-lines=MAX-LINES`: 每个命令行最多使用 MAX-LINES 个非空输入行
`-l[LINES]`: `-L` 的旧式别名,裸形式默认 1 行
`-I R-STR`: 用从标准输入读取的名称替换初始参数中的 R-STR
`-i, --replace[=R-STR]`: `-I` 的旧式别名,裸形式默认 `{}`
`-P, --max-procs=MAX-PROCS`: 一次最多运行 MAX-PROCS 个进程
`-a, --arg-file=FILE`: 从文件而不是标准输入读取项
`-E EOF`: 设置逻辑 EOF 字符串
`-e[EOF], --eof[=EOF]`: `-E` 的旧式别名;裸形式会保持 EOF 关闭
`--show-limits`: 显示命令行长度限制
`-t, --verbose`: 在执行之前在标准错误输出上打印命令行
`-0, --null`: 输入项以空字符而不是空白字符终止
`-d, --delimiter=DELIM`: 输入项以 DELIM 而不是空白字符终止
`-o, --open-tty`: 在子进程中重新打开控制台输入
`-r, --no-run-if-empty`: 输入为空时不执行命令
`-x, --exit`: 命令行过长时直接退出
`--process-slot-var=VAR`: 为子进程导出槽位变量 | 从输入执行命令,SmallVector 优化;stdin item 仍然保持 literal 数据,而命令模板参数现在会走共享通配符策略,因此 `xargs cmd ... *.txt` 在 Windows 上会更接近 shell 先展开后的 GNU 调用,同时在 glob 无匹配时仍回退到原始字面 token;父目录段里的通配符如 `dir*\\*.txt`、`dir?\\*.txt` 现在也会展开,不再错误地保持字面值;像 `\\x` 这种不完整 hex escape、以及未知 named escape 现在也会返回更具体的 delimiter-escape 诊断,而不再退回旧的泛化 single-character 错误 |
### 追加文本处理
| 命令 | 状态 | 优先级 | 描述 | 参数选项 | 实现说明 |
|------|------|--------|------|----------|----------|
| `ptx` | ✅ 已实现 | 低 | 生成文件内容的排列索引 | `-f, --ignore-case`: 忽略大小写差异
`-r, --references`: 只输出单词引用
`-w, --width`: 设置输出宽度 | 排列索引生成 |
| `expand` | ✅ 已实现 | 低 | 将制表符转换为空格 | `-t, --tabs=tab1[,tab2]...`: 设置制表位
`-i, --initial`: 不转换非空白后的制表符 | 制表符转空格 |
| `unexpand` | ✅ 已实现 | 低 | 将空格转换为制表符 | `-t, --tabs=tab1[,tab2]...`: 设置制表位
`-a, --all`: 转换所有空白,而不仅仅是开头
`-f, --first-only`: 只转换第一段空格
`-U, --no-utf8`: 将文件输入按原始 8 位字节处理 | 空格转制表符;默认文件读取会剥掉 UTF-8 BOM,而 `-U` 会保留它 |
| `fold` | ✅ 已实现 | 低 | 将每一行折叠到指定宽度 | `-w, --width=WIDTH`: 使用 WIDTH 列而不是 80 列
`-b, --bytes`: 按字节而不是按列计数
`-c, --characters`: 按字符而不是按列计数
`-s, --spaces`: 在空格处断行 | 行折叠;普通换行模式会先去掉 CRLF 记录尾部的 `\r`,`-c` 现在会按 UTF-8 code point 计数而不会把多字节字符劈开,默认列宽模式也会保持常见 UTF-8 宽字符完整并按 2 列处理 |
| `fmt` | ✅ 已实现 | 低 | 简单的最佳文本排版器 | `-w, --width=WIDTH`: 最大行宽(默认 75)
`-T, --tab-width=TABWIDTH`: 计算宽度时把 tab 视为 TABWIDTH 个空格,但输出中保留 tab
`-p, --prefix=STRING`: 只格式化以 STRING 开头的行
`-P, --skip-prefix=STRING`: 原样保留匹配行
`-x, --exact-prefix`: `-p` 不再忽略前导空白
`-X, --exact-skip-prefix`: `-P` 不再忽略前导空白
`-c, --crown-margin`: 保留 crown margin
`-m, --preserve-headers`: 识别简单邮件头并并入 continuation 行
`-t, --tagged-paragraph`: 保留带标签的段落
`-s, --split-only`: 只拆分长行
`-u, --uniform-spacing`: 统一空格 | 文本格式化;prefix 模式现在会保留匹配前缀的附着空白,`-x` 会让带缩进的行不再被 `-p` 命中,`-P/-X` 则补齐了和微软版一致的常见 skip-prefix 路径,`-m` 现在能保留简单 `Header: value` 邮件头块并合并 continuation 行,同时采用我们实测到的微软式更宽正文折行,而带 tab 缩进的段落现在也会按 Microsoft/Coreutils 默认的 8 列 tab 宽度计算,除非显式用 `-T` 覆盖 |
| `nl` | ✅ 已实现 | 低 | 为文件的行编号 | `-b, --body-numbering=STYLE`: 为正文行编号
`-n, --number-format=FORMAT`: 按 FORMAT 插入行号
`-s, --number-separator=STRING`: 在行号后添加 STRING
`-f, --footer-numbering=STYLE`: 页脚编号样式
`-h, --header-numbering=STYLE`: 页眉编号样式
`-i, --line-increment=NUMBER`: 行号递增量
`-l, --join-blank-lines=NUMBER`: 合并空行数量
`-v, --starting-line-number=NUMBER`: 起始行号
`-w, --number-width=NUMBER`: 行号宽度 | 行编号 |
| `paste` | ✅ 已实现 | 低 | 合并文件的行 | `-d, --delimiters=LIST`: 使用 LIST 中的字符代替 TAB
`-s, --serial`: 一次处理一个文件而不是并行
`-z, --zero-terminated`: 用 NUL 结束行 | 行合并 |
| `pr` | ✅ 已实现 | 低 | 为打印格式转换文本文件 | `+FIRST_PAGE[:LAST_PAGE]`: 从第 FIRST_PAGE 页开始(并可停止于 LAST_PAGE)
`-C, --columns=NUM`: 输出 NUM 列并按列向下打印
`-a, --across`: 横向排列列
`-d, --double-space`: 双倍行距
`-h, --header=HEADER`: 使用居中的 HEADER 代替文件名
`-l, --length=PAGE_LENGTH`: 设置页长度
`-o, --indent=MARGIN`: 为每行加上 MARGIN 个空格
`-T, --omit-pagination`: 省略分页控制 | 打印格式文本 |
| `tr` | ✅ 已实现 | 中 | 转换或删除字符 | `-c, -C, --complement`: 使用 SET1 的补集
`-d, --delete`: 删除 SET1 中的字符
`-s, --squeeze-repeats`: 压缩重复字符序列
`-t, --truncate-set1`: 将 SET1 截断到 SET2 长度 | 字符转换与删除;参数个数诊断现在会区分缺少 `SET2`、`-d -s` 缺少压缩集合,以及纯删除模式多余集合,并附带 GNU 风格 help hint |
| `rev` | ✅ 已实现 | 低 | 反转文件中的每一行 | 无选项 | 行反转 |
| `tac` | ✅ 已实现 | 低 | 反向连接并打印文件 | `-b, --before`: 将分隔符放在前面而不是后面
`-r, --regex`: 将分隔符解释为正则表达式
`-s, --separator=STRING`: 使用 STRING 作为分隔符 | 反向拼接 |
| `shuf` | ✅ 已实现 | 低 | 打乱输入行 | `-e, --echo`: 将每个参数视为输入行
`-i, --input-range=LO-HI`: 将 LO 到 HI 的数字视为输入行
`-n, --head-count=COUNT`: 最多输出 COUNT 行
`-o, --output=FILE`: 将结果写入 FILE
`--random-seed=STRING`: 用 STRING 生成可复现结果
`--random-source=FILE`: 从 FILE 读取随机字节
`-r, --repeat`: 允许重复输出
`-z, --zero-terminated`: 使用 NUL 作为行终止符 | 行打乱;`--random-seed` 现在会按更接近 Microsoft/uutils 的 seeded 算法为洗牌和 `-r` 抽样提供确定性结果,`--random-source` 现在会按更接近 GNU/Microsoft 的熵回收适配路径做重复抽样和洗牌选择,重复 `-n/--head-count` 会取最小值,并且会与 `--random-source` 冲突报错 |
| `split` | ✅ 已实现 | 低 | 将文件拆分为多个片段 | `-l, --lines=NUMBER`: 每个输出文件放 NUMBER 行
`-b, --bytes=SIZE`: 每个输出文件放 SIZE 字节
`-C, --line-bytes=SIZE`: 每个输出文件放 SIZE 字节但不拆分行
`--filter=COMMAND`: 对每个输出文件运行 COMMAND
`-n, --number=CHUNKS`: 生成 CHUNKS 份
`-a, --suffix-length=N`: 生成长度为 N 的后缀
`-d, --numeric-suffixes[=FROM]`: 使用数字后缀
`-x, --hex-suffixes[=FROM]`: 使用十六进制后缀
`--additional-suffix=SUFFIX`: 追加 SUFFIX
`-e, --elide-empty-files`: 不生成空输出文件
`-t, --separator=SEP`: 使用 SEP 作为记录分隔符
`-u, --unbuffered`: 每行后刷新输出
`--verbose`: 打印输出文件名 | 文件拆分;输入参数走统一通配符策略,歧义匹配会被拒绝,必须最终解析成恰好一个文件;第 3 个位置参数现在会按 GNU 风格报 `extra operand` 并附带 help hint |
| `csplit` | ✅ 已实现 | 低 | 按上下文将文件拆分为多个片段 | `-f, --prefix=PREFIX`: 使用 PREFIX 作为输出文件名前缀
`-b, --suffix-format=FORMAT`: 使用 FORMAT 作为后缀格式
`-n, --digits=DIGITS`: 使用指定位数
`-k, --keep-files`: 出错时不删除输出文件
`--suppress-matched`: 在输出中省略匹配行
`-z, --elide-empty-files`: 省略空输出文件
`-s, -q, --quiet, --silent`: 不打印输出文件大小 | 按上下文拆分;输入参数走统一通配符策略,歧义匹配会被拒绝,必须最终解析成恰好一个文件;缺少输入文件或 pattern 时现在会附带 GNU 风格 help hint;行号 pattern 配合 `--suppress-matched` 现在也会保留 GNU/uutils 风格的空尾分片语义 |
| `join` | ✅ 已实现 | 低 | 按共同字段连接两个文件的行 | `-1 FIELD`: 使用文件 1 的 FIELD 作为连接键
`-2 FIELD`: 使用文件 2 的 FIELD 作为连接键
`-a FILE-NUMBER`: 打印无法配对的文件 NUMBER 行
`--check-order`: 检查输入是否正确排序
`--nocheck-order`: 不检查排序顺序
`-e STRING`: 用 STRING 填充空输出字段
`--header`: 将每个文件的首行视为表头
`-i, --ignore-case`: 比较键时忽略大小写
`-j FIELD`: 两个文件都使用 FIELD 作为连接键
`-o FIELD-LIST`: 按 FIELD-LIST 输出字段
`-t, --separator=CHAR`: 使用 CHAR 作为输入和输出字段分隔符
`-v FILE-NUMBER`: 仅打印无法配对的文件 NUMBER 行
`-z, --zero-terminated`: 使用 NUL 作为行终止符 | 行连接 |
| `comm` | ✅ 已实现 | 低 | 逐行比较两个已排序文件 | `-1`: 屏蔽仅在 FILE1 中出现的行
`-2`: 屏蔽仅在 FILE2 中出现的行
`-3`: 屏蔽两个文件都出现的行
`--check-order`: 检查输入是否正确排序
`--nocheck-order`: 不检查排序顺序
`--output-delimiter=STRING`: 在列之间使用 STRING
`--total`: 打印总计
`-z, --zero-terminated`: 使用 NUL 作为行终止符 | 已排序文件比较 |
### 文件工具补充
| 命令 | 状态 | 优先级 | 描述 | 参数选项 | 实现说明 |
|------|------|--------|------|----------|----------|
| `basename` | ✅ 已实现 | 低 | 去掉目录和后缀的文件名 | `-a, --multiple`: 支持多个参数并分别处理
`--mul`: `--multiple` 的缩写别名
`-s, --suffix=SUFFIX`: 移除尾随 SUFFIX;即使 `SUFFIX` 为空也会隐含多参数模式
`--suf`: `--suffix` 的缩写别名
`-z, --zero`: 每个输出行以 NUL 结束
`--ze`: `--zero` 的缩写别名
GNU 风格 operand 诊断:补齐 missing operand help hint,与非 `-a` 模式下的 extra operand 拒绝
纯斜杠根路径如 `/`、`//`、`///` 现在统一归一成单个根分隔符输出
GNU 后缀规则:当 suffix 恰好等于整个剩余 basename 时不剥离 | 文件名处理 |
| `dirname` | ✅ 已实现 | 低 | 去掉最后一个路径组件 | `-z, --zero`: 每个输出行以 NUL 结束
GNU 风格 operand 诊断:补齐 missing operand help hint
纯斜杠根路径如 `/`、`//`、`///` 现在统一归一成单个根分隔符输出
`/usr/` 这类绝对顶层路径会正确返回 `/` | 文件名处理 |
| `readlink` | ✅ 已实现 | 低 | 打印解析后的符号链接或规范化文件名 | `-f, --canonicalize`: 跟随每个符号链接进行规范化
`-e, --canonicalize-existing`: 跟随每个符号链接并要求存在
`-m, --canonicalize-missing`: 跟随每个符号链接并允许缺失
`-n, --no-newline`: 不输出尾随分隔符
`-q, -s, --quiet, --silent`: 抑制大多数诊断
`-v, --verbose`: 输出诊断
`-z, --zero`: 每个输出行以 NUL 结束
GNU 风格 operand 诊断:missing operand help hint | 符号链接解析;默认诊断保持 quiet,canonicalization mode 选项族与 `-q/-s/-v` 现在都按最后一次出现生效,且 `POSIXLY_CORRECT` 现在会恢复 GNU 风格 regular-file 诊断并忽略 `-q/-s` |
| `cmp` | ✅ 已实现 | 低 | 逐字节比较两个文件 | `-b, --print-bytes`: 打印不同的字节
`-i, --ignore-initial=SKIP` / `-i SKIP1:SKIP2`: 跳过一个或两个输入开头的指定字节数
`-l, --verbose`: 为每个差异输出字节编号和差异字节值
`-n, --bytes=LIMIT`: 最多比较 LIMIT 个字节
`-s, --quiet`: 抑制常规输出
`FILE1 FILE2 [SKIP1 [SKIP2]]`: 接受 GNU 风格的位置 skip 参数 | 字节比较;默认差异输出现在会同时包含 byte 和 line 编号,`-l/--verbose` 会按 GNU 风格以相对比较起点的字节号和八进制字节值列出全部差异,`-l/--verbose` 与 `-s/--quiet` 这组输出模式现在按 GNU/uutils 风格“最后一次出现生效”,GNU 的位置参数 `SKIP1`/`SKIP2` 与 `-i SKIP1:SKIP2` 现在也可用,skip 计数接受 GNU 风格的十进制/八进制/十六进制前缀和常见字节后缀,并且“跳过长度超过较短文件”不再把比较范围算下溢 |
| `cpio` | ✅ 已实现 | 低 | 复制归档中的文件 | `-o, --create`: 创建归档
`-i, --extract`: 从归档中提取文件
`-t, --list`: 列出归档内容
`-d, --make-directories`: 必要时创建前导目录
`-m, --preserve-modification-time`: 创建文件时保留修改时间 | 归档复制 |
| `pathchk` | ✅ 已实现 | 低 | 检查文件名是否有效或可移植 | `-p, --portability`: 按 POSIX 检查
`-P, --posix`: 按 POSIX 检查
`--help`: 显示帮助
`--version`: 输出版本信息
GNU 风格 operand 诊断:missing operand 的 help hint 保持在 stderr
当前文件系统检查会接受正常的 Windows 盘符绝对路径,而重复分隔符/尾随分隔符现在也不会再在 `-P` 风格检查下被误判成 `empty file name`;默认模式下空路径诊断也改成了 GNU/uutils 形状的 `pathchk: '': No such file or directory`,并且多个非法 operand 会逐条单独报告 | 路径有效性检查 |
| `sync` | ✅ 已实现 | 低 | 将缓存写入持久存储 | `-d, --data`: 只同步命名文件的数据
`-f, --file-system`: 同步包含这些文件的文件系统 | 文件系统同步;现在已接受 GNU `sync` 的 `-d/--data` 和 `-f/--file-system` 选项表面,已存在目录参数在普通 `sync` 和 `--data` 下现在也会成功,`--data` 缺少文件参数时会按更接近 uutils 的形状报 `--data needs at least one argument`,`--data` 与 `--file-system` 组合时现在也会按互斥选项失败,`--file-system` 现在会把已存在的文件和目录参数都视为文件系统引用并接受,无效选项会输出 GNU 风格 `unrecognized option` 加 help hint,而多个缺失文件参数现在都会逐条输出更接近 GNU/uutils 的 `error opening 'FILE': No such file or directory` 诊断而不是在第一个失败处停止;Windows 侧仍是近似实现 |
| `shred` | ✅ 已实现 | 中 | 覆盖文件以隐藏其内容 | `-f, --force`: 更改权限以允许写入
`-n, --iterations=N`: 覆盖 N 次而不是默认的 3 次
`-s, --size=N`: 仅处理 N 字节
`-u, --remove`: 覆盖后删除并截断文件
`-v, --verbose`: 显示进度
`-z, --zero`: 最后再用零覆盖一次 | 安全删除 |
| `md5sum` | ✅ 已实现 | 低 | 计算并检查 MD5 摘要 | `-b, --binary`: 二进制模式读取
`-c, --check`: 读取并检查校验和
`--tag`: 创建 BSD 风格校验和
`-t, --text`: 文本模式读取
`-z, --zero`: 每个输出行以 NUL 结束 | MD5 校验和 |
| `sha1sum` | ✅ 已实现 | 低 | 计算并检查 SHA1 摘要 | `-b, --binary`: 二进制模式读取
`-c, --check`: 读取并检查校验和
`--tag`: 创建 BSD 风格校验和
`-t, --text`: 文本模式读取
`-z, --zero`: 每个输出行以 NUL 结束 | SHA1 校验和 |
| `sha224sum` | ✅ 已实现 | 低 | 计算并检查 SHA224 摘要 | `-b, --binary`: 二进制模式读取
`-c, --check`: 读取并检查校验和
`--tag`: 创建 BSD 风格校验和
`-t, --text`: 文本模式读取
`-z, --zero`: 每个输出行以 NUL 结束 | SHA224 校验和 |
| `sha256sum` | ✅ 已实现 | 低 | 计算并检查 SHA256 摘要 | `-b, --binary`: 二进制模式读取
`-c, --check`: 读取并检查校验和
`--tag`: 创建 BSD 风格校验和
`-t, --text`: 文本模式读取
`-z, --zero`: 每个输出行以 NUL 结束 | SHA256 校验和 |
| `sha384sum` | ✅ 已实现 | 低 | 计算并检查 SHA384 摘要 | `-b, --binary`: 二进制模式读取
`-c, --check`: 读取并检查校验和
`--tag`: 创建 BSD 风格校验和
`-t, --text`: 文本模式读取
`-z, --zero`: 每个输出行以 NUL 结束 | SHA384 校验和 |
| `sha512sum` | ✅ 已实现 | 低 | 计算并检查 SHA512 摘要 | `-b, --binary`: 二进制模式读取
`-c, --check`: 读取并检查校验和
`--tag`: 创建 BSD 风格校验和
`-t, --text`: 文本模式读取
`-z, --zero`: 每个输出行以 NUL 结束 | SHA512 校验和 |
| `b2sum` | ✅ 已实现 | 低 | 计算并检查 BLAKE2 摘要 | `-b, --binary`: 二进制模式读取
`-c, --check`: 读取并检查校验和
`--tag`: 创建 BSD 风格校验和
`-t, --text`: 文本模式读取
`-z, --zero`: 每个输出行以 NUL 结束 | BLAKE2 校验和 |
| `od` | ✅ 已实现 | 低 | 以八进制和其他格式转储文件 | `-A, --address-radix=RADIX`: 选择偏移量输出的基数
`-j, --skip-bytes=BYTES`: 先跳过 BYTES 字节
`-N, --read-bytes=BYTES`: 限制读取字节数
`-t, --format=TYPE`: 选择输出格式
`-v, --output-duplicates`: 不用 * 标记重复行
`-w, --width BYTES`: 每行输出 BYTES 字节 | 八进制转储 |
| `xxd` | ✅ 已实现 | 低 | 制作十六进制转储或反向转换 | `-b, --bits`: 以位模式输出
`-c, --cols COLS`: 每行输出 COLS 个字节
`-g, --groupsize BYTES`: 每组字节数
`-l, --len LENGTH`: 处理到 LENGTH 字节为止
`-p, --ps`: 以连续 hexdump 风格输出
`-r, --reverse`: 将 hexdump 逆向为二进制
`-s, --seek OFFSET`: 从 OFFSET 开始 | 十六进制转储与反向转换 |
| `patch` | ✅ 已实现 | 中 | 将 diff 文件应用到原始文件 | `-p NUM`: 去掉文件名前 NUM 层前缀
`-i, --input=PATCHFILE`: 从 PATCHFILE 读取补丁
`-d, --directory=DIR`: 切换到 DIR
`-R, --reverse`: 假设补丁是反向顺序
`-N, --forward`: 假设补丁是旧新文件交换顺序 | 补丁应用 |
| `diff3` | ✅ 已实现 | 低 | 比较三个文件 | `-e`: 输出 ed 脚本
`-3`: 像 -e 一样,但包含第三个文件的修改
`-m, --merge`: 输出合并后的文件
`-i`: 像 -e 一样,但括起修改
`-A`: 把旧版本到你的所有修改都合并进去
`-E`: 忽略旧版本到你的修改
`-X`: 覆盖重叠修改 | 三方文件比较;文件参数走统一通配符策略,并且必须最终解析成恰好三个文件;多余参数现在会附带 GNU 风格的 help hint |
| `sdiff` | ✅ 已实现 | 低 | 并排合并文件差异 | `-o FILE`: 将输出写入 FILE
`-w NUM`: 设置输出宽度
`-l`: 对共同行只打印左列
`-s, --suppress-common-lines`: 不打印共同行
`-E`: 忽略 tab 展开差异
`-b`: 忽略空白数量差异
`-W`: 忽略全部空白差异
`-B`: 忽略全空白行差异 | 并排差异;空文件现在可正常处理,文件参数在固定双文件检查前会先按统一通配符规则解析,多余参数会附带 GNU 风格 help hint |
### 系统信息
| 命令 | 状态 | 优先级 | 描述 | 参数选项 | 实现说明 |
|------|------|--------|------|----------|----------|
| `which` | ✅ 已实现 | 高 | 在 PATH 中定位命令 | `-a, --all`: 打印每个参数的所有匹配路径名
`--read-alias`, `--skip-alias`: 读取/跳过别名展开
`--read-functions`, `--skip-functions`: 读取/跳过 shell 函数展开
`--skip-dot`: 跳过 PATH 中以点开头的目录
`--show-dot`: 允许显示以点开头的目录
`--skip-tilde`: 跳过 PATH 中以波浪号开头的目录
`--show-tilde`: 允许显示以波浪号开头的目录
`--tty-only`: 仅在 tty 上显示匹配结果 | 路径搜索,支持 PATHEXT,SmallVector 优化 |
| `env` | ✅ 已实现 | 中 | 在修改的环境中运行命令 | `-i, --ignore-environment`: 从空环境开始
`-u, --unset=NAME`: 从环境中删除变量,可重复
`-0, --null`: 打印环境时每项以 NUL 结束;如果同时给出 COMMAND,会按 GNU/uutils 风格以退出码 `125` 拒绝
`-S, --split-string=S`: 用当前轻量 parser 拆分 S;未闭合引号现在会按 GNU 风格失败并返回 `125`
`-v, --debug`: 在标准错误输出处理诊断信息;重复 debug flag(如 `-vv`)时还会额外打印原始输入参数
`-a, --argv0=STRING`: 覆盖传给子进程的 `argv[0]`,但仍执行原始程序
`-C, --chdir=DIR`: 在运行 COMMAND 前切换工作目录;按 GNU 语义必须同时提供命令
`NAME=VALUE`: 添加或覆盖环境变量
`COMMAND [ARG]...`: 在修改后的环境中运行命令 | 使用 Windows environment block 打印或执行命令;parse-time 的非法 option 现在也会按 GNU/uutils 风格附带标准 help hint 并返回 `125`,`-a/--argv0`、`-C/--chdir`、`-S/--split-string` 现在按“最后一次出现生效”,`-0/--null` 现在只允许用于打印环境,与 command 组合时会按 GNU/uutils 风格输出 `cannot specify --null (-0) with command`,找不到子命令时现在也会按 GNU 风格输出 `failed to run command 'CMD': No such file or directory` 并保留退出码 `127`;完整 GNU `-S` 解析、剩余 GNU debug 边角和信号控制仍是缺口 |
| `pwd` | ✅ 已实现 | 高 | 打印工作目录 | `-L, --logical`: 优先使用仍然指向当前目录的绝对 `PWD` 环境变量
`-P, --physical`: 避免所有符号链接 | 工作目录显示;`-L` 现在只会在 `PWD` 是绝对路径、仍解析到当前目录且路径分量中不含 `.`/`..` 时采用它,存在 `POSIXLY_CORRECT` 时裸 `pwd` 现在会切到 logical 默认值,`-L/-P` 按“最后一次出现生效”,多余的非选项参数现在会按 GNU 形状在 stderr 输出 `ignoring non-option arguments` warning |
| `ps` | ✅ 已实现 | 高 | 报告进程状态 | `-e, -A`: 选择所有进程
`-a`: 选择所有进程,但不包括会话领导和没有关联终端的进程
`-x`: 选择没有控制 tty 的进程
`-f`: 完整格式列表
`-l`: 长格式
`-u USER`: 按有效用户 ID 或名称选择
`-w`: 宽输出
`--no-headers`: 不打印头
`--sort=KEY`: 按列排序 | 进程列表和过滤;这条是仓库本地实现,不对应 GNU Coreutils 手册页 |
| `chmod` | ✅ 已实现 | 中 | 更改文件模式位 | `-c, --changes`: 类似详细,但仅在做出更改时报告
`-f, --silent, --quiet`: 禁止大多数错误消息
`-v, --verbose`: 为处理的每个文件输出诊断
`-R, --recursive`: 递归更改文件和目录
`--reference=RFILE`: 使用 RFILE 的模式而不是 MODE 值 | 文件权限修改;文件参数走统一通配符策略,`-R --preserve-root /` 现在会按 GNU/uutils 风格提前触发 failsafe,`--reference=RFILE FILE...` 现在会按 Windows 只读属性近似复制 reference 模式,并保留 GNU 形状的缺失 reference 诊断;`u+gr` 这类 malformed mode 现在也会在访问文件前按 GNU 风格失败并附带 help hint,GNU 风格的负 symbolic mode 形态如 `-w`、`file -w` 和重复的 `-w -w` 也已接受 |
| `chgrp` | ✅ 已实现 | 中 | 更改文件组 | `-c, --changes`: 类似详细,但仅在做出更改时报告
`-f, --silent, --quiet`: 禁止大多数错误消息
`-v, --verbose`: 为每个处理的文件输出诊断
`-R, --recursive`: 递归处理文件和目录
`--from=GROUP`: 仅当当前组匹配 GROUP 时才更改
`--reference=RFILE`: 使用 RFILE 的组而不是显式 GROUP | 文件组修改;非法 `GROUP` 参数现在会按 GNU/uutils 风格提前报 `invalid group: 'GROUP'` 并附带标准 help hint,非法 `--from=GROUP` 现在会按更接近 uutils 的形状报 `invalid user: 'GROUP'`,`--from=GROUP` 现在会先按每个现有目标当前的 Windows 组名做过滤,再决定是否应用 `--reference` 或直接改组尝试,numeric `--from=gid` 和 `--from=:gid` 现在也会被接受,并按目标组 SID 最后一个 RID 做 Windows 近似匹配,缺失的 `--reference=RFILE` 文件现在会报 `failed to get attributes of 'RFILE': No such file or directory`,`--reference=RFILE FILE...` 现在接受 GNU 的参数形状并会先校验 reference 文件是否存在,只有在 `--from` 过滤命中时 `-v --reference=RFILE FILE...` 才会在 stderr 输出 retained-group 诊断,`--preserve-root -R /` 现在也会在真正遍历前按 GNU/uutils 风格输出两行 failsafe 诊断并拒绝执行,实际组变更行为仍受 Windows 限制 |
| `chcon` | ✅ 已实现 | 中 | 更改 SELinux 文件上下文 | `--reference=RFILE`: 使用 RFILE 的安全上下文
`-u, --user=USER`: 设置 user 组件
`-r, --role=ROLE`: 设置 role 组件
`-t, --type=TYPE`: 设置 type 组件
`-l, --range=RANGE`: 设置 range 组件
`-R, --recursive`: 递归处理文件和目录
`-H`、`-L`、`-P`、`-h`、`--dereference`: 保留 GNU 风格 symlink/dereference 参数表面
`-v, --verbose`: 为每个处理的文件输出诊断 | Windows 兼容占位实现:先校验 GNU 形状的命令行和已存在文件参数,再明确报告 Windows 不支持 SELinux 文件上下文 |
| `chroot` | ✅ 已实现 | 中 | 更改根目录 | `--groups=GROUP1,GROUP2...`: 指定补充组
`--userspec=USER:GROUP`: 在运行 COMMAND 前指定用户和组
`--skip-chdir`: 更改 root 后不切换到 `/`
`NEWROOT [COMMAND [ARG]...]`: GNU 参数形式 | Windows 兼容占位实现:接受 GNU 形状的命令行,校验 `NEWROOT` 必须是已存在目录,然后明确报告 Windows 不支持真正的 root 目录切换 |
| `date` | ✅ 已实现 | 中 | 打印或设置系统日期/时间 | `-d, --date=STRING`: 显示由 STRING 描述的时间
`--debug`: 打印日期解析调试信息
`-f, --file=DATEFILE`: 从文件读取日期字符串
`-I, --iso-8601[=TIMESPEC]`: ISO 8601 输出
`-r, --reference=FILE`: 参考文件时间
`--resolution`: 输出时间分辨率
`-R, --rfc-email`: RFC 5322 风格日期
`--rfc-3339=TIMESPEC`: RFC 3339 风格输出
`-s, --set=STRING`: 设置系统时间
`-u, --utc, --universal`: 打印或设置协调世界时(UTC)
`+FORMAT`: 输出格式字符串 | 日期/时间显示和格式化 |
| `kill` | ✅ 已实现 | 高 | 向进程发送信号 | `-l, --list`: 列出所有信号名称
`-s, --signal=SIGNAL`: 发送指定的信号
`-t, --table`: 以表格列出信号
`SIGNAL`: 信号编号或名称(例如,-9、-KILL、-15、-TERM) | 进程信号发送 |
### 系统工具
| 命令 | 状态 | 优先级 | 描述 | 参数选项 | 实现说明 |
|------|------|--------|------|----------|----------|
| `df` | ✅ 已实现 | 中 | 报告文件系统磁盘空间使用情况 | `-h, --human-readable`: 以 1024 的幂打印大小
`-H, --si`: 以 1000 的幂打印大小
`-k`: 使用 1K 块
`-T, --print-type`: 打印文件系统类型
`-i, --inodes`: 输出 inode 形状的列;Windows 使用占位列
文件参数走统一通配符策略
`-t, --type=TYPE`、`-x, --exclude-type=TYPE`、`-a, --all`: 在 GNU 兼容表中继续跟踪 | 磁盘空间报告 |
| `du` | ✅ 已实现 | 中 | 估算文件空间使用情况 | `-a, --all`: 为所有文件输出计数,而不仅仅是目录
`-B, --block-size=SIZE`: 按 SIZE 缩放后输出
`-b, --bytes`: 等价于 apparent-size 且块大小为 1
`-c, --total`: 产生总计
`-d, --max-depth=N`: 仅输出低于命令行参数 N 或更少级别的条目
`-h, --human-readable`: 以 1024 的幂打印大小
`--si`: 以 1000 的幂打印大小
`-H, --dereference-args`: 在 Windows 上接收 GNU dereference-args 形状
`-k`: 使用 1K 块
`-m`: 使用 1M 块
`-0, --null`: 每条输出记录以 NUL 而不是换行结束
`-S, --separate-dirs`: 父目录输出不再包含子目录总量
`--time[=WORD]`: 为每条输出显示最新的所选时间戳;支持 `mtime`、`atime|access|use`、`ctime|status`
`-X, --exclude-from=FILE`: 从文件读取排除 glob pattern
`--files0-from=FILE`: 从文件读取 NUL 分隔的 path operand
`-s, --summarize`: 仅显示每个参数的总计 | 文件/目录大小估算;`--files0-from` 会拒绝额外命令行 path,文件参数其余情况走统一通配符策略,`--exclude-from` 与 `--exclude` 共享同一套匹配逻辑,块计数向上取整,且 `ctime`/`status` 当前在 Windows 上映射为 creation time |
### 网络
| 命令 | 状态 | 优先级 | 描述 | 参数选项 | 实现说明 |
|------|------|--------|------|----------|----------|
| `ping` | ❌ 未实现 | 高 | 向网络主机发送 ICMP ECHO_REQUEST | `-c COUNT`: 发送 COUNT 个 ECHO_REQUEST 数据包后停止
`-i INTERVAL`: 在发送每个数据包之间等待 INTERVAL 秒 | 尚未实现 |
| `curl` | ❌ 未实现 | 中 | 从服务器传输数据或向服务器传输数据 | `-s, --silent`: 静默模式
`-o, --output`: 将输出写入文件而不是 stdout | 尚未实现 |
### 其他
| 命令 | 状态 | 优先级 | 描述 | 参数选项 | 实现说明 |
|------|------|--------|------|----------|----------|
| `help` | ✅ 已实现 | 高 | 显示命令的帮助信息 | `COMMAND`: 显示特定命令的帮助 | 使用命令元数据生成帮助 |
| `man` | ✅ 已实现 | 低 | 显示手册页 | `COMMAND`: 显示某个命令的手册页 | 仓库本地手册查找,处理 `.exe` |
| `jobs` | ✅ 已实现 | 中 | 显示当前 shell 中作业的状态 | `-l, --list`: 除常规信息外还列出进程 ID
`-n, --names`: 只列出自上次通知后状态发生变化的作业
`-p, --pid`: 只列出作业进程组首进程的 ID
`-r, --running`: 只列出正在运行的作业
`-s, --stopped`: 只列出已停止的作业 | 作业状态显示 |
| `bg` | ✅ 已实现 | 中 | 在后台恢复一个作业 | `JOB_SPEC`: 作业标识,或 `-` 表示当前作业 | 后台恢复 |
| `fg` | ✅ 已实现 | 中 | 在前台恢复一个作业 | `JOB_SPEC`: 作业标识,或 `-` 表示当前作业 | 前台恢复 |
| `wait` | ✅ 已实现 | 中 | 等待进程结束 | `PID`: 要等待的进程 ID | 进程等待 |
| `export` | ✅ 已实现 | 中 | 设置环境变量 | 无选项 | 环境变量导出 |
| `unset` | ✅ 已实现 | 中 | 取消设置 shell 变量的值和属性 | 无选项 | 变量取消设置 |
| `stty` | ✅ 已实现 | 中 | 打印和修改终端行设置 | `-a, --all`: 打印所有当前设置
`-g, --save`: 以 stty 可读格式打印所有当前设置
`-F, --file=DEVICE`: 打开并使用指定设备而不是 stdin | 终端设置 |
| `iconv` | ✅ 已实现 | 中 | 在两种编码之间转换文本 | `-f, --from-code=NAME`: 原始文本的编码
`-t, --to-code=NAME`: 输出编码
`-l, --list`: 列出所有已知编码字符集
`-c`: 忽略无效字符
`-s`: 抑制警告 | 编码转换 |
| `localedef` | ✅ 已实现 | 中 | 编译 locale 定义文件 | `-f, --charmap=FILE`: FILE 中定义的字符名
`-i, --inputfile=FILE`: locale 定义文件
`-u, --alias-file=FILE`: locale 名称别名文件 | locale 定义编译 |
| `renice` | ✅ 已实现 | 中 | 调整正在运行进程的优先级 | `-n, --priority NUM`: 指定调度优先级
`-p, --pid PID`: 将参数解释为进程 ID
`-u, --user USER`: 将参数解释为用户名
`-g, --pgrp PGID`: 将参数解释为进程组 ID | 调整进程优先级 |
| `test` | ✅ 已实现 | 高 | 检查文件类型并比较值 | `-e FILE`: 文件存在
`-f FILE`: 文件是普通文件
`-d FILE`: 文件是目录
`-z STRING`: 字符串长度为零
`-n STRING`: 字符串长度非零
`STRING1 = STRING2`: 字符串相等
`INTEGER1 -eq INTEGER2`: 整数相等 | 文件类型检查和值比较 |
| `[` | ✅ 已实现 | 高 | 检查文件类型并比较值 | 同 `test` | `test` 的别名 |
| `true` | ✅ 已实现 | 低 | 返回成功结果 | 无选项 | 正常执行时始终返回 0,同时 `-V/--version` 现在也会成功,而不是被误判成未知选项 |
| `false` | ✅ 已实现 | 低 | 返回失败结果 | 无选项 | 正常执行时始终返回 1,同时 `-V/--version` 现在也会成功,而不是被误判成未知选项 |
| `exit` | ✅ 已实现 | 高 | 退出 shell | 无选项 | 简单退出调用,带有管道结构 |
| `clear` | ✅ 已实现 | 高 | 清除终端屏幕 | 无选项 | 使用系统调用清除屏幕 |
| `reset` | ✅ 已实现 | 低 | 重新初始化终端 | 无选项 | 终端重置 |
| `cd` | ✅ 已实现 | 高 | 更改当前目录 | `-L, --logical`: 强制遵循符号链接
`-P, --physical`: 使用物理目录结构而不遵循符号链接 | 使用 SetCurrentDirectory API,带有管道结构 |
| `type` | ❌ 未实现 | 中 | 描述命令类型 | `COMMAND`: 描述特定命令 | 尚未实现 |
| `alias` | ❌ 未实现 | 低 | 为命令创建别名 | `NAME=VALUE`: 定义别名
`-p`: 打印所有定义的别名 | 尚未实现 |
### 补充命令
| 命令 | 状态 | 优先级 | 描述 | 参数选项 | 实现说明 |
|------|------|--------|------|----------|----------|
| `disown` | ✅ 已实现 | 中 | 从当前 shell 中移除作业 | `-a, --all`: 未给出 JOB_SPEC 时移除所有作业
`-h, --help`: 显示帮助
`-r, --running`: 仅移除正在运行的作业 | 作业移除 |
| `wait` | ✅ 已实现 | 中 | 等待进程结束 | `PID`: 要等待的进程 ID | 进程等待 |
| `export` | ✅ 已实现 | 中 | 设置环境变量 | 无选项 | 环境变量导出 |
| `unset` | ✅ 已实现 | 中 | 取消设置 shell 变量的值和属性 | 无选项 | 变量取消设置 |
| `logname` | ✅ 已实现 | 低 | 打印用户的登录名 | 无常规选项 | 登录名显示;dispatcher 层的 `-V/--version` 现在也会成功 |
| `whoami` | ✅ 已实现 | 低 | 打印有效用户 ID | 无常规选项 | 用户 ID 显示;dispatcher 层的 `-V/--version` 现在也会成功 |
| `id` | ✅ 已实现 | 中 | 打印用户和组信息 | `-a, --all`: 忽略,仅用于兼容其他版本
`-g, --group`: 仅打印有效组 ID
`-G, --groups`: 打印所有组 ID
`-n, --name`: 打印名称而不是数字
`-r, --real`: 打印真实 ID 而不是有效 ID
`-u, --user`: 仅打印有效用户 ID | 用户和组信息 |
| `users` | ✅ 已实现 | 低 | 打印当前登录用户的用户名 | 无选项 | 已登录用户显示 |
| `who` | ✅ 已实现 | 低 | 显示当前登录信息 | `-a, --all`: 等同于 -b -d --login -p -r -t -T -u
`-b, --boot`: 上次系统启动时间
`-d, --dead`: 打印死进程
`-H, --heading`: 打印列标题
`-l, --login`: 打印系统登录进程
`-m`: 仅显示 stdin 关联的主机名和用户
`-p, --process`: 打印 init 派生的活动进程
`-q, --count`: 打印登录名和在线人数
`-r, --runlevel`: 打印当前 runlevel
`-s, --short`: 仅打印名称、行和时间
`-t, --time`: 打印上次系统时钟变更时间
`-u, --users`: 列出已登录用户 | 用户信息 |
| `groups` | ✅ 已实现 | 低 | 打印用户所属的组 | `--help`: 显示帮助
`--version`: 输出版本信息 | 组信息 |
| `hostname` | ✅ 已实现 | 低 | 显示或设置系统主机名 | `-a, --alias`: 别名
`-A, --all-fqdns`: 所有长主机名
`-d, --domain`: DNS 域名
`-f, --fqdn`: FQDN
`-i, --ip-address`: 主机名地址
`-I, --all-ip-addresses`: 主机所有地址
`-s, --short`: 短主机名
`-y, --yp, --nis`: NIS/YP 域名 | 主机名显示 |
| `hostid` | ✅ 已实现 | 低 | 打印当前主机的数值标识 | 无常规选项 | 主机 ID 显示;dispatcher 层的 `-V/--version` 现在也会成功 |
| `uname` | ✅ 已实现 | 中 | 打印系统信息 | `-a, --all`: 打印全部信息
`-s, --kernel-name`: 打印内核名
`-n, --nodename`: 打印网络节点主机名
`-r, --kernel-release`: 打印内核版本
`-v, --kernel-version`: 打印内核版本字符串
`-m, --machine`: 打印机器硬件名
`-p, --processor`: 打印处理器类型
`-i, --hardware-platform`: 打印硬件平台
`-o, --operating-system`: 打印操作系统 | 系统信息 |
| `arch` | ✅ 已实现 | 低 | 打印机器架构 | 无常规选项 | 架构显示;dispatcher 层的 `-V/--version` 现在也会成功 |
| `uptime` | ✅ 已实现 | 中 | 显示系统运行了多久 | `-p, --pretty`: 以简洁格式显示运行时间
`-s, --since`: 显示系统启动时间
`-h, --help`: 显示帮助
`-V, --version`: 输出版本信息 | 系统运行时间 |
| `free` | ✅ 已实现 | 中 | 显示系统空闲和已用内存 | `-b, --bytes`: 以字节显示
`-k, --kilo`: 以 KB 显示
`-m, --mega`: 以 MB 显示
`-g, --giga`: 以 GB 显示
`--tera`: 以 TB 显示
`-h, --human`: 以人类可读格式显示
`-l, --lohi`: 显示 low/high memory 统计 | 内存使用显示 |
| `lsof` | ✅ 已实现 | 低 | 列出打开的文件 | 无选项 | 打开文件列表 |
| `nproc` | ✅ 已实现 | 低 | 打印可用处理单元数量 | `--all`: 打印已安装的处理单元数量
`--ignore=N`: 尽量排除 N 个处理单元 | 处理器数量 |
| `numfmt` | ✅ 已实现 | 低 | 在人类可读字符串和数值之间转换 | `-d, --delimiter=X`: 使用 X 代替空白作为分隔符
`-f, --format=FORMAT`: 使用 printf 风格浮点格式
`--from=UNIT`: 将输入自动缩放到 UNIT
`--to=UNIT`: 将输出自动缩放到 UNIT
`--round=METHOD`: 使用指定舍入方式
`--padding=N`: 输出填充到 N 个字符 | 数字格式化 |
| `column` | ✅ 已实现 | 低 | 列化列表 | `-c, --output-width=WIDTH`: 设置输出宽度
`-t, --table`: 识别表格列数
`-s, --separator SEPARATOR`: 指定输入分隔符
`-o, --output-separator STRING`: 指定表格输出列分隔符
`-x, --fillrows`: 先填充行再填充列 | 列格式化 |
| `jq` | ✅ 已实现 | 中 | 命令行 JSON 处理器 | `-c, --compact-output`: 紧凑输出
`-r, --raw-output`: 输出原始字符串
`-s, --slurp`: 将所有输入读入数组
`-R, --raw-input`: 读取原始字符串
`-M, --monochrome-output`: 不给 JSON 上色 | JSON 处理 |
| `mktemp` | ✅ 已实现 | 中 | 创建临时文件或目录 | `-d, --directory`: 创建目录而不是文件
`-u, --dry-run`: 不实际创建任何内容
`-q, --quiet`: 出错时静默失败
`--suffix=SUFFIX`: 在模板后追加 SUFFIX;SUFFIX 里不能包含路径分隔符
`-p, --tmpdir[=DIR]`: 将模板视为相对于 DIR
`-t`: 使用临时目录路径生成模板 | 临时文件/目录创建;显式 `--suffix=SUFFIX` 现在会在模板替换后追加后缀,并在 suffix 含有 `/` 或 `\` 时给出接近 GNU/Microsoft 的诊断,同时在 `--tmpdir` 或模板自带目录时保留生成路径输出 |
| `mkfifo` | ✅ 已实现 | 中 | 创建命名管道(FIFO) | `-m, --mode=MODE`: 设置权限位
`-Z`: 将 SELinux 安全上下文设为默认类型
`--context[=CTX]`: 设置 SELinux 安全上下文
`NAME...`: 要创建的 FIFO 名称 | Windows 兼容占位实现:校验 GNU 形状的参数表面,保留 GNU 风格的 `missing operand` 和 `File exists` 诊断,并明确报告 Windows 不支持文件系统 FIFO |
| `mknod` | ✅ 已实现 | 中 | 创建特殊文件 | `-m, --mode=MODE`: 设置权限位
`-Z`: 将 SELinux 安全上下文设为默认类型
`--context[=CTX]`: 设置 SELinux 安全上下文
`NAME TYPE [MAJOR MINOR]`: GNU 参数形式,`TYPE` 支持 `b`、`c`/`u`、`p` | Windows 兼容占位实现:校验 GNU 参数组合,例如 `p` 与 `b/c` 的主次设备号规则,保留 GNU 风格的 `missing operand` 和 `File exists` 诊断,并明确报告 Windows 不支持特殊文件 |
| `mpicalc` | ✅ 已实现 | 低 | 简单任意精度计算器 | 无选项 | 任意精度计算 |
| `hmac256` | ✅ 已实现 | 低 | 计算 HMAC-SHA256 | `--help`: 显示帮助
`--version`: 输出版本信息 | HMAC 计算 |
| `pinky` | ✅ 已实现 | 低 | 轻量 finger | `-l`: 长格式输出
`-b`: 省略用户主目录和 shell
`-h`: 省略用户项目文件
`-p`: 省略用户计划文件
`-s`: 短格式输出 | 用户信息 |
| `seq` | ✅ 已实现 | 低 | 打印数字序列 | `-f, --format=FORMAT`: 使用 printf 风格浮点格式
`-s, --separator=STRING`: 用 STRING 分隔数字
`-t, --terminator=STRING`: 用 STRING 取代最终换行
`-w, --equal-width`: 通过补零对齐宽度 | 序列生成;缺少 operand 和多余 operand 时现在都会附带 GNU 风格 help hint,`-w` 现在也会按 GNU/uutils 形状拒绝显式 `-f/--format` 字符串,`-t/--terminator` 现在会只替换最后一个输出分隔符而不改变中间分隔符,零增量现在也会使用更接近 GNU/uutils 的 `invalid Zero increment value: 'ARG'` 诊断 |
| `sleep` | ✅ 已实现 | 低 | 延迟指定时间 | `NUMBER[SUFFIX]`: 暂停 NUMBER 秒 | 睡眠延迟;缺少 operand 时现在会附带 GNU 风格 help hint,非法或负数 duration 现在会按 GNU 形状输出 `invalid time interval` 诊断,多个非法 duration operand 现在会在最终 help hint 前全部列出,前导空白仍会被接受,而尾随空白现在会按 GNU/uutils 形状拒绝 |
| `yes` | ✅ 已实现 | 低 | 重复输出字符串 | `STRING...`: 重复前先用单个空格拼接的字符串参数 | 重复输出;GNU/uutils 风格的多参数调用现在会先把全部参数用单个空格拼接,而不是只使用第一个参数,同时 `-V/--version` 现在也会成功,而不是被误判成未知选项 |
| `printf` | ✅ 已实现 | 高 | 格式化并打印数据 | `FORMAT`: 格式字符串
`ARGUMENTS`: 要格式化的参数 | 格式化输出 |
## 实现指南
### 一般结构
每个命令应遵循以下一般结构:
1. **模块声明**:以 `export module cmd.;` 开头
2. **导入**:导入必要的模块(`import core;`、`import utils;` 等)
3. **常量命名空间**:定义命令特定的常量
4. **选项定义**:使用 `OPTION` 宏定义命令选项
5. **管道组件**:实现用于命令处理的管道组件
6. **命令实现**:实现主命令逻辑
7. **注册**:使用 `REGISTER_COMMAND` 宏注册命令
### 示例结构
```cpp
export module cmd.echo;
import core;
import utils;
using cmd::meta::OptionMeta;
using cmd::meta::OptionType;
namespace echo_constants {
// 命令特定的常量可以在这里定义
}
// 定义选项
export auto constexpr ECHO_OPTIONS =
std::array{
OPTION("-n", "--no-newline", "不输出尾随换行符"),
OPTION("-e", "--escape", "启用反斜杠转义的解释"),
};
namespace echo_pipeline {
namespace cp = core::pipeline;
// 验证参数
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;
}
// 从参数构建文本
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;
}
// 处理命令
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 */
"显示一行文本。",
/* examples */
" echo Hello World 显示 'Hello World'\n"
" echo -n Hello 显示 'Hello' 但不带尾随换行符\n"
" echo -e Hello\\nWorld 在单独的行上显示 'Hello' 和 'World'",
/* 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;
// 使用 CommandContext 获取选项
bool no_newline = ctx.get("--no-newline", false);
bool escape = ctx.get("--escape", false);
// 如果启用,处理转义序列
if (escape) {
// 实现转义序列处理
}
// 输出结果
std::cout << text;
if (!no_newline) {
std::cout << std::endl;
}
return 0;
}
```
### 最佳实践
1. **管道架构**:使用管道组件进行模块化处理
2. **类型安全**:使用 `CommandContext` 进行类型安全的选项访问
3. **错误处理**:使用 `core::pipeline::Result` 进行一致的错误处理
4. **文档**:为每个命令提供清晰的文档
5. **测试**:使用各种输入和选项测试命令
6. **性能**:在适当的地方优化性能
7. **兼容性**:尽可能遵循 POSIX 标准
### 性能优化
WinuxCmd 使用自定义容器优化性能:
#### SmallVector
栈分配的向量,具备小缓冲优化 (SBO):
- 小规模 (< 64 元素) 时比 std::vector 快 5-10 倍
- 典型命令场景下减少 80%+ 的堆分配
- 超过容量时自动回退到堆分配
#### ConstexprMap
编译时哈希映射表,用于固定大小的键值对:
- 零初始化开销
- 运行时 O(1) 查找
- 完美适用于配置表和映射
**已优化的命令**:
- find, cat, env, mv, xargs, grep, sed, head, tail, tee, wc, uniq, which (使用 SmallVector)
- tail (使用 ConstexprMap 实现后缀乘数:K, M, G, T, P, E)
详细信息请参阅 [custom_containers.md](custom_containers.md)。
## 测试
每个命令应使用以下内容进行测试:
1. **基本功能**:测试没有选项的命令
2. **所有选项**:单独测试每个选项
3. **组合选项**:一起测试多个选项
4. **边缘情况**:测试空输入、大输入等
5. **错误情况**:测试无效输入和选项
## 迁移指南
### 从旧实现迁移
要将命令从旧实现迁移到新的基于管道的结构:
1. **更新模块声明**:使用 `export module cmd.;`
2. **添加导入**:添加必要的导入(`import core;`、`import utils;`)
3. **定义选项**:使用 `OPTION` 宏定义选项
4. **创建管道命名空间**:实现管道组件
5. **更新命令实现**:使用 `CommandContext` 进行选项访问
6. **注册命令**:使用新的 `REGISTER_COMMAND` 宏
## 参考实现
`echo.cppm` 文件作为新的基于管道的架构的参考实现。它演示了:
1. **管道组件**:单独的验证和处理逻辑
2. **选项处理**:使用 `CommandContext` 进行类型安全的选项访问
3. **错误处理**:使用 `core::pipeline::Result` 进行错误报告
4. **命令注册**:正确使用 `REGISTER_COMMAND` 宏
所有新命令都应遵循此模式,以确保一致性和可维护性。
### GNU 兼容补充
下面这些命令在源码里已经存在,但主表里还没有完整收录;它们大多有 GNU Coreutils 对照页,适合作为当前一轮的补充清单。像 `getconf`、`cal`、`less`、`top`、`watch`、`cygpath`、`dos2unix`、`unix2dos`、`u2d`、`d2u`、`tzset`、`tree` 这类本地或第三方命令,仍按仓库本地工具另行维护。
| 命令 | 状态 | 优先级 | 描述 | 参数选项 | 实现说明 |
|------|------|--------|------|----------|----------|
| `chown` | ✅ 已实现 | 中 | 更改文件所有者和组 | `-R, --recursive`: 递归处理
`-v, --verbose`: 为每个处理的文件输出诊断
`--from=CURRENT_OWNER:CURRENT_GROUP`: 仅在当前 owner/group 匹配时变更
`--reference=RFILE`: 使用参考文件的 owner/group | Windows 上仍主要做状态报告和路径遍历,实际所有权变更受权限限制;但显式 `OWNER` / `GROUP` 名字以及 `--from` 提供的 current owner/group 名字现在都会先做校验,非法名字会按 GNU 形状提前报 `invalid user` / `invalid group`,`::`、`..`、`1001:`、`1001.` 这类 malformed spec 现在也会按更接近 GNU/uutils 的形状报 `invalid group` / `invalid spec`,`OWNER.`、`OWNER.GROUP` 这类 dot-separated 形式现在会先输出更接近 GNU/uutils 的 `warning: '.' should be ':'`,`--from` 现在会先按现有目标当前的 Windows owner/group 做过滤,再决定是否应用 `--reference` 或继续直接变更尝试,不匹配的目标会保持不变且 `-v` 会输出 retained-ownership 诊断,命中过滤条件时也不再输出旧的 Windows 占位 `not supported` 诊断,direct 模式下像 `:`、`CURRENT_OWNER:` 这种本来就不需要变更的 spec 现在也会按 GNU/uutils 风格输出 retained-ownership,而不是伪造 `changing ownership ... to` 行,缺失的 reference 文件现在会报 `failed to get attributes of 'RFILE': No such file or directory`,`-v --reference=RFILE FILE...` 现在会在 stderr 输出 retained-ownership 诊断,`--preserve-root -R /` 现在也会在真正遍历前按 GNU/uutils 风格输出两行 failsafe 诊断并拒绝执行 |
| `install` | ✅ 已实现 | 中 | 复制文件并设置属性 | `-b, --backup`: 为已存在的目标文件创建备份
`-c`: 兼容旧 Unix 的占位参数
`-C`: 兼容旧 Unix 的占位参数
`-d, --directory`: 把所有参数当作目录名
`-D`: 创建 DEST 除最后一段外的所有前缀
`-g, --group`: 设置组所有权
`-m, --mode`: 设置权限模式
`-o, --owner`: 设置所有权
`-p, --preserve-timestamps`: 保留源文件时间戳
`-s, --strip`: 去掉符号表
`--strip-program`: 指定 strip 程序
`-S, --suffix`: 覆盖默认备份后缀
`-t, --target-directory`: 指定目标目录
`-T, --no-target-directory`: 不把最后一个参数特殊视为目录
`-v, --verbose`: 打印创建目录时的名称
`--preserve-context`: 保留 SELinux 安全上下文
`-Z`: 将目标文件的 SELinux 上下文设为默认值 | 目前更像文件复制+属性应用的简化实现,Windows 上的 owner/mode/SELinux 效果仍不完整;GNU 语义还要继续对齐 `-C`、`--compare`、`--debug`、`--backup=CONTROL` 等细节 |
| `link` | ✅ 已实现 | 中 | 创建硬链接 | 无常规选项 | GNU `link` 本身是无选项命令;当前实现在缺失源文件失败和目标已存在失败时都会输出接近 GNU 的 `cannot create link 'LINK' to 'FILE'` 诊断,而不是原始 Win32 错码;参数个数错误也已收敛到 uutils 形状的 `2 values required`,无效选项现在也会输出 GNU 风格 `unrecognized option` 加 help hint,`-V/--version` 现在也会成功,源文件通配符现在遵循共享文件输入策略:恰好一个匹配会展开,多匹配时也会像 shell 展开后的多 operand 一样折回到 `2 values required`,零匹配回退到字面路径 |
| `dir` | ✅ 已实现 | 中 | 默认按列列出目录内容 | `OPTION... FILE...`: 以 GNU `dir` wrapper 语义转发给 `ls -C` | `ls` 的 wrapper,默认输出格式是列模式;转发给 `ls` 的 argv 现在会保留原始 option/operand 顺序,因此 `-a`、`-d` 这类 GNU wrapper 选项会真正传到 `ls`,同时也会按 Windows `CreateProcessW` 引号规则保留带空格的单个参数,不会再在进入 `ls` 前被拆开 |
| `nice` | ✅ 已实现 | 中 | 以修改后的调度优先级运行程序 | `-n, --adjustment=N`: 调整优先级增量
命令前的 GNU 旧式 adjustment 写法如 `-1`、`--1`、`-+1` 现在也接受 | 当前实现把 niceness 映射为 Windows 进程优先级类,数值语义与 GNU 的真正 niceness 仍不完全相同;裸 `nice` 现在会打印当前 niceness,显式给出 adjustment 却没有 command 时现在会按 GNU/uutils 风格以 `A command must be given with an adjustment.` 和退出码 `125` 失败,命令开始前的旧式 bare adjustment 如 `-1`、`--1`、`-+1` 现在会改写到 GNU `-n` 语义,超大正负 adjustment 现在会收敛到边界值而不是在选项解析阶段失败,`-2+4` 这类非法 adjustment 会以 GNU 形状 usage error 返回 `125`,invalid option 这类 parse error 也会返回 `125`,子命令参数现在也会按 Windows `CreateProcessW` 规则正确引用,避免带空格的单个参数被拆开;子命令不存在时现在会输出 GNU 形状的 `failed to run command 'CMD': ...` 诊断,并保留约定的 `127` not-found 退出码 |
| `nohup` | ✅ 已实现 | 中 | 让命令忽略挂断信号 | `-a, --append`: 追加输出到文件
GNU 风格 operand/parse 诊断:missing operand 和 invalid option 的 help hint 保持在 stderr,且 `POSIXLY_CORRECT` 下这两类 usage error 返回 `127`,默认返回 `125` | GNU `nohup` 本身没有常规选项;当前实现保留了一个本地 `-a` 扩展,并通过分离进程模拟挂断隔离;子命令参数现在也会按 Windows `CreateProcessW` 引号规则正确保留带空格的单个参数;当子命令不存在时,现在会输出 GNU 形状的 `failed to run command 'CMD': ...` 诊断,并保留约定的 `127` not-found 退出码 |
| `runcon` | ✅ 已实现 | 中 | 在 SELinux 进程上下文中运行命令 | `-c, --compute`: 修改前先计算进程转换上下文
`-u, --user=USER`: 设置 user 组件
`-r, --role=ROLE`: 设置 role 组件
`-t, --type=TYPE`: 设置 type 组件
`-l, --range=RANGE`: 设置 range 组件
`CONTEXT COMMAND [ARG]...`: GNU plain-context 形式 | Windows 兼容占位实现:接受 GNU 形状的参数表面,校验 plain-context 形式必须带 COMMAND,并明确报告 Windows 不支持 SELinux 进程上下文 |
| `printenv` | ✅ 已实现 | 中 | 打印全部或部分环境变量 | `-0, --null`: 每行以 NUL 结束 | 目前支持全量枚举和指定变量输出;空值变量仍会输出空记录,部分命中/部分缺失时会保留已找到的输出并返回 `1`,包含 `=` 的变量名 operand 现在会静默忽略并让退出码保持 `1`,无效选项现在会按 GNU/uutils 风格返回退出码 `2` 并附带标准 help hint,全量枚举时会跳过 Windows 隐藏的 `=...` 伪环境项 |
| `stat` | ✅ 已实现 | 中 | 显示文件或文件系统状态 | `-L, --dereference`: 跟随符号链接
`-f, --file-system`: 显示文件系统状态而不是文件状态
`-c, --format`: 使用指定格式并自动追加换行
`-t, --terse`: 以简洁格式输出
`--printf`: 类似 `--format`,但解释反斜杠转义且不自动追加换行
常用格式字段:`%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 文件状态输出;missing operand 现在也会带 GNU 风格的 `Try 'stat --help' for more information.` 提示,且 `-t`、`-c/--format`、`--printf` 现在按 GNU/uutils 风格“最后一次出现生效”,owner/group 和 symlink 细节仍是 Windows 近似语义 |
| `stdbuf` | ✅ 已实现 | 中 | 以修改后的缓冲方式运行命令 | `-i, --input`: 调整标准输入缓冲
`-o, --output`: 调整标准输出缓冲
`-e, --error`: 调整标准错误缓冲 | 现在只调整父进程侧缓冲并启动子进程;missing command、invalid mode 和 invalid option 这类 usage/parse error 现在会按 GNU/uutils 风格返回 `125`,并把 help hint 保持在 stderr;子命令参数现在也会按 Windows `CreateProcessW` 引号规则正确保留带空格的单个参数;GNU `stdbuf` 仍会把缓冲策略更准确地作用到被执行程序本身 |
| `timeout` | ✅ 已实现 | 中 | 以时间限制运行命令 | `-s, --signal`: 超时后发送的信号
`-k, --kill-after`: 超时后再等多久发送 KILL
`--foreground`: 允许受管命令使用前台 TTY
`--preserve-status`: 让退出码跟随被执行命令 | 现有实现基于 Windows 进程等待和终止;`missing operand` / `missing command` 现在会附带 GNU 风格 help hint,并返回退出码 `125`,parse-time 的非法 option 现在也会带标准 help hint 并返回 `125`,`--foreground` 在 Windows 上也不再让 timeout 失效,非法 signal / duration / kill-after 用法现在也会返回 `125` 并输出 GNU 形状诊断,verbose 超时诊断也会优先打印 `TERM` 这类信号名,且 `-s0` 配合 `-k/--kill-after` 时现在会把强制终止延后到 KILL 阶段并返回 GNU/uutils 形状的 `137`,同时子进程参数现在会按 Windows `CreateProcessW` 规则引用,带空格的单个参数不会再被拆开;GNU 版本更深的信号语义、退出码约定和前台/后台细节还需要继续收敛 |
| `vdir` | ✅ 已实现 | 中 | 默认按长列表列出目录内容 | `OPTION... FILE...`: 以 GNU `vdir` wrapper 语义转发给 `ls -l` | `ls` 的 wrapper,默认输出格式是长列表;转发给 `ls` 的 argv 现在会保留原始 option/operand 顺序,因此 `-a`、`-d` 这类 GNU wrapper 选项会真正传到 `ls`,同时也会按 Windows `CreateProcessW` 引号规则保留带空格的单个参数,不会再在进入 `ls` 前被拆开 |
| `tty` | ✅ 已实现 | 低 | 打印标准输入连接的终端名 | `-s, --silent`: 只返回退出状态,不输出内容
`--quiet`: `--silent` 的别名 | 当前实现检查控制台存在性并返回状态;多余 operand 和 invalid option 现在都会保留 GNU 形状的错误并把 help hint 一起写到 stderr,统一返回 2,非 tty stdin 的 silent / 非 silent 模式返回 1,非 silent 输出时 stdout 提前断开现在会按 GNU/uutils 形状返回 3,tty 检测本身仍是简化的 Windows console 判定 |
| `truncate` | ✅ 已实现 | 低 | 缩短或扩展文件大小 | `-c, --no-create`: 不创建文件
`-s, --size`: 设置或调整文件大小
`-r, --reference`: 以 RFILE 的大小为准 | `-o` 还未实现;GNU 的 size 解析、相对长度和 I/O 块语义还需要继续补 |
| `unlink` | ✅ 已实现 | 低 | 删除单个文件 | 无常规选项 | GNU `unlink` 基本是无选项命令;当前实现在缺失路径和目录场景下会输出接近 GNU 的 `cannot unlink` 诊断,而不是原始 Win32 错码,operand 错误的 help hint 也走 stderr,并且现在会带出具体的多余参数;无效选项现在也会输出 GNU 风格 `unrecognized option` 加 help hint,`-V/--version` 现在也会成功;通配符输入如果展开成多个路径也会按 GNU 风格报 `extra operand`,零匹配时则回退到字面路径;目录符号链接/联接现在也会按 GNU 语义删除链接本身,而不删目标目录 |
| `test_bracket` | ✅ 已实现 | 高 | `[` 的内部实现入口 | 同 `test` | 这是 `test`/`[` 共享语法的内部命令壳,主要用于注册和分派,不应单独引入新的 GNU 语义 |
| `env` | ✅ 已实现 | 中 | 在修改后的环境中运行命令 | `-i, --ignore-environment`: 从空环境开始
`-u, --unset=NAME`: 从环境中移除变量;可重复
`-0, --null`: 打印环境时以 NUL 结尾;与 COMMAND 同用时按 GNU/uutils 风格以退出码 `125` 拒绝
`-f, --file=FILE`: 先从简化 `.env` 文件读取 `NAME=VALUE`,再应用 `-u` 与命令行赋值;空行和 `#` 注释会忽略
`-S, --split-string=S`: 用当前轻量解析器拆分参数;未闭合引号会以退出码 `125` 失败
`-v, --debug`: 向标准错误输出调试信息;重复调试 flag 如 `-vv` 也会打印原始输入参数
`-a, --argv0=STRING`: 覆盖传给子进程的 `argv[0]`,但仍执行原始程序
`-C, --chdir=DIR`: 运行 COMMAND 前切换工作目录;按 GNU 用法必须同时提供命令
`NAME=VALUE`: 添加或覆盖环境变量
`COMMAND [ARG]...`: 在修改后的环境中运行命令 | 通过物化后的 Windows 环境块打印或执行;parse-time 非法选项现在也会按 GNU/uutils 风格附带标准 help hint 并返回 `125`,`-f/--file` 现在会先加载简单、带 trim 的 `.env` 条目,再应用 `-u` 与命令行 `NAME=VALUE`,文件打开失败按普通命令失败返回而不是 usage error,`-a/--argv0`、`-C/--chdir`、`-S/--split-string` 现在按最后一次出现生效,`-0/--null` 只允许用于打印环境,和命令同用时会按 `cannot specify --null (-0) with command` 失败,子命令缺失时会输出 GNU 形状的 `failed to run command 'CMD': ...` 诊断并保留常规 `127` not-found 退出码;完整 GNU `-S` 解析以及剩余 debug/signal 细节仍是缺口 |