教學:microsoft/coreutils — Windows 原生 UNIX 工具集完整指南
第 1 章:專案定位與價值主張
這個專案解決什麼問題?
長久以來,Windows 使用者若想使用 ls、grep、find、cat 等 UNIX 核心指令,必須仰賴 WSL (Windows Subsystem for Linux)、Cygwin、Git Bash 或 MSYS2 等額外環境。這些方案各有限制:WSL 需要完整 Linux 子系統、Cygwin 相容層效能開銷大、Git Bash 指令集有限。
microsoft/coreutils 是 Microsoft 官方推出的解決方案——將 uutils/coreutils(GNU coreutils 的 Rust 重寫版)連同 findutils 與 grep 打包為單一原生 Windows 執行檔 (native binary),無需虛擬化層、無需相容層、無需 Linux kernel。
關鍵特色
- 原生 Windows binary:Rust 編譯的
.exe,不需要額外 runtime - 70+ 指令:coreutils + findutils + grep 一次到位
- WinGet 安裝:
winget install Microsoft.Coreutils一行搞定 - DOS 相容:
find與sort自動偵測 DOS/GNU 語法,不破壞既有 Batch script - PowerShell 7.4+ 整合:修正引號解析、處理 alias 衝突
- MIT License (MIT 授權):可自由使用於商用環境
誰適合使用?
| 角色 | 使用情境 |
|---|---|
| 跨平台開發者 | 在 Windows、Linux、macOS 間切換時保持一致的 CLI 體驗 |
| DevOps / SRE | Windows CI/CD pipeline 中使用 UNIX 工具 |
| 系統管理員 | 替代笨重的 Cygwin / Git Bash |
| Batch / PowerShell 使用者 | 漸進式引入 UNIX 工具,不破壞既有腳本 |
| 教育訓練 | 在 Windows 環境學習 UNIX 指令 |
第 2 章:安裝指南
方法一:WinGet(推薦)
1# 安裝
2winget install Microsoft.Coreutils
3
4# 驗證
5coreutils --version
6# 預期輸出:coreutils 2026.5.29 (multi-call binary)
7
8# 列出所有可用指令
9coreutils --list
方法二:從 Release 下載
- 前往 Release Page
- 下載
.exe安裝檔 - 執行安裝精靈,可選擇:
- 加入系統 PATH
find預設使用 GNU 版本或 DOS 版本sort預設使用 GNU 版本或 DOS 版本
方法三:從原始碼編譯
1# 前置條件
2# - Rust 1.88.0+
3# - Visual Studio Build Tools (MSVC)
4# - git
5
6# 取得原始碼(含 submodule)
7git clone --recurse-submodules https://github.com/microsoft/coreutils.git
8cd coreutils
9
10# 編譯(Release 模式)
11cargo build --release
12
13# 執行檔位於 target/release/coreutils.exe
安裝後驗證
1# 確認 PATH
2where.exe ls
3# 預期:C:\Program Files\coreutils\cmd\ls.exe
4
5# 測試基本指令
6ls --version
7grep --version
8find --version
9
10# 列出所有 70+ 指令
11coreutils --list | wc -l
解除安裝
1winget uninstall Microsoft.Coreutils
第 3 章:核心架構解析 (Architecture Deep Dive)
整體架構
microsoft/coreutils 採用 multi-call binary (多重呼叫二進位) 架構——所有 70+ 個指令編譯進同一個 coreutils.exe,安裝時以 hardlink (硬連結) 建立各指令的 .exe(如 ls.exe、cat.exe),因此看似 700MB 的安裝目錄實際只佔一份二進位檔的空間。
graph TB
subgraph "使用者輸入"
CMD["cmd.exe
ls -la"]
PS["PowerShell 7.4+
ls -la"]
end
subgraph "指令分派層 (main.rs)"
ENTRY["coreutils.exe 入口
(multi-call binary)"]
NAME["檔名解析
binary_path() → name()"]
MAP["phf::OrderedMap
util_map() 查表"]
end
subgraph "啟發式分流 (nthelpers.rs)"
FIND_H["find_heuristic()
DOS /C /I vs GNU -name -type"]
SORT_H["sort_heuristic()
DOS /R vs GNU --reverse"]
REG["Windows Registry
DefaultFind / DefaultSort"]
end
subgraph "上游實作 (deps/)"
UU_CORE["uutils/coreutils
70+ Rust 指令"]
UU_FIND["uutils/findutils
find + xargs"]
UU_GREP["uutils/grep
grep + egrep + fgrep"]
NT_FIND["ntfind (Rust)
DOS find 相容"]
NT_SORT["ntsort (C)
DOS sort 相容"]
end
subgraph "PowerShell 整合"
PWSH["pwsh-install.ps1
Profile 注入"]
TMPL["pwsh-install-template.ps1
PSReadLine 修正"]
end
CMD --> ENTRY
PS --> ENTRY
ENTRY --> NAME
NAME --> MAP
MAP -->|"find"| FIND_H
MAP -->|"sort"| SORT_H
MAP -->|"其他指令"| UU_CORE
FIND_H -->|"DOS 風格"| NT_FIND
FIND_H -->|"GNU 風格"| UU_FIND
FIND_H -->|"不確定"| REG
REG -->|"DefaultFind=0"| NT_FIND
REG -->|"DefaultFind=1"| UU_FIND
SORT_H -->|"DOS 風格"| NT_SORT
SORT_H -->|"GNU 風格"| UU_CORE
SORT_H -->|"不確定"| REG
UU_GREP -.->|"獨立 crate"| MAP
PWSH -.->|"安裝時執行"| PS
TMPL -.->|"注入 profile"| PWSH
Multi-call Binary 運作原理
- 進入點:
main()取得執行檔路徑(例如C:\...\ls.exe) - 名稱解析:
name()擷取檔名 stem(ls) - 查表分派:在編譯時期透過
build.rs+phf_codegen產生的 perfect hash map 中查找對應的uumain函式 - 執行:呼叫該指令的
uumain(args)並以其回傳值作為 process exit code
find/sort 啟發式分流詳解
nthelpers.rs 中的 find_heuristic() 實作了精巧的命令列分析:
| 偵測到的 pattern | 判定結果 |
|---|---|
/C, /I, /N, /V 等 DOS switch | → DOS find (ntfind) |
-name, -type, -exec, (, ) 等 GNU expression | → GNU find (findutils) |
| 引號開頭的第一個參數(無 backslash escape) | → 可能是 DOS(搜尋字串) |
backslash escape (\") | → GNU style |
| 都不符合 | → 查 Registry DefaultFind 值 |
建置流程
build.rs 執行三件事:
- generate_uutils_map():解析
Cargo.toml中所有uu_*依賴,透過phf_codegen產生靜態 hash map - compile_ntsort():用
cccrate 編譯deps/ntsort/sort.c(原生 Windows sort 相容層) - compile_manifest():嵌入 Windows 應用程式 manifest 與圖示
第 4 章:使用方式詳解
基本檔案操作
1# 列出檔案(含隱藏檔、詳細資訊、人類可讀大小)
2ls -lah
3
4# 複製檔案(遞迴、保留屬性)
5cp -rp source_dir/ dest_dir/
6
7# 移動/重新命名
8mv old_name.txt new_name.txt
9
10# 刪除(遞迴、強制)
11rm -rf temp_dir/
12
13# 建立目錄(含父目錄)
14mkdir -p path/to/new/dir
15
16# 建立空檔案或更新時間戳記
17touch newfile.txt
文字處理
1# 檢視檔案內容(附行號)
2cat -n config.txt
3
4# 取前/後 N 行
5head -20 large_log.txt
6tail -f running.log
7
8# 搜尋文字(遞迴、忽略大小寫、顯示行號)
9grep -rin "error" logs/
10
11# 排序與去重
12sort data.csv | uniq -c | sort -rn
13
14# 欄位擷取
15cut -d',' -f1,3 data.csv
16
17# 字元替換/刪除
18cat file.txt | tr 'a-z' 'A-Z'
19cat file.txt | tr -d '\r' # 移除 CR 字元
20
21# 字數/行數統計
22wc -l *.txt
搜尋檔案
1# GNU find 語法
2find . -name "*.log" -type f -mtime -7
3
4# 搭配 xargs 批次處理
5find . -name "*.tmp" -print0 | xargs -0 rm -f
6
7# 結合 grep 全文搜尋
8find . -name "*.py" -exec grep -l "import torch" {} +
Pipeline 與資料處理
1# 統計各副檔名的檔案數量
2find . -type f | sed 's/.*\.//' | sort | uniq -c | sort -rn
3
4# CSV 處理:取第 2 欄、排序、去重
5cut -d',' -f2 data.csv | sort | uniq
6
7# 產生序列
8seq 1 100 | shuf | head -10
9
10# Base64 編解碼
11echo "Hello World" | base64
12echo "SGVsbG8gV29ybGQK" | base64 -d
Windows 特有注意事項
| 事項 | 說明 | 解決方式 |
|---|---|---|
| CRLF 換行 | Windows 文字檔使用 \r\n | 用 tr -d '\r' 或注意 $ 匹配 |
無 /dev/null | Windows 無此裝置檔 | 使用 NUL 替代 |
| 無 POSIX signals | 無 SIGHUP、SIGPIPE | Ctrl+C (SIGINT) 正常運作 |
| 路徑分隔符 | / 與 \ 都可用 | 部分指令輸出 \,影響 piping |
| Symlink 權限 | 讀取不需提權 | 建立需 Developer Mode 或管理員 |
| PowerShell escape | 仍是 ` 而非 \ | find . `( -name "*.txt" `) |
第 5 章:應用場景
場景一:跨平台 CI/CD Pipeline
1# GitHub Actions — Windows runner 使用 UNIX 指令
2jobs:
3 build:
4 runs-on: windows-latest
5 steps:
6 - run: winget install Microsoft.Coreutils --accept-package-agreements
7 - run: |
8 find src/ -name "*.rs" | wc -l
9 grep -r "TODO" src/ | tee todos.txt
10 cat todos.txt | wc -l
場景二:開發者日常工作流
1# 快速查看 Git 專案結構
2find . -maxdepth 2 -type f -not -path './.git/*' | head -30
3
4# 搜尋所有 Python 檔案中的 import
5grep -rn "^import\|^from" --include="*.py" .
6
7# 批次重新命名
8ls *.jpeg | while read f; do mv "$f" "${f%.jpeg}.jpg"; done
9
10# 統計程式碼行數(排除空行與註解)
11find src/ -name "*.rs" -exec cat {} + | grep -v '^\s*$' | grep -v '^\s*//' | wc -l
場景三:系統管理
1# 找出大檔案
2find C:\ -type f -size +100M 2>NUL
3
4# 磁碟用量分析
5du -sh *
6
7# 系統資訊
8uptime
9hostname
10nproc
11df -h
場景四:取代 Cygwin/Git Bash
| 功能 | Cygwin | Git Bash | microsoft/coreutils |
|---|---|---|---|
| 安裝大小 | 數百 MB~數 GB | ~300 MB | ~15 MB(單一 binary) |
| 啟動速度 | 慢(相容層) | 中等 | 快(原生) |
| 指令完整度 | 最完整 | 有限 | 70+ 常用指令 |
| DOS 相容 | 無 | 無 | find/sort 自動分流 |
| 官方支援 | 社群 | Git 團隊 | Microsoft |
第 6 章:資安掃描報告
掃描範圍
- 掃描對象:
src/(Rust + PowerShell)、build.rs、Cargo.toml、deps/ntsort/sort.c、deps/ntfind/、coreutils.iss - 掃描項目:
eval/exec、unsafe區塊、硬編碼機密、網路呼叫、Registry 操作、PowerShell injection
綜合評級:🟢 低風險
詳細發現
1. unsafe 區塊(Rust)— 🟡 已知風險,合理使用
共 12 處 unsafe 使用,全部為 Windows API FFI 呼叫所必需:
| 檔案 | 用途 | 風險評估 |
|---|---|---|
main.rs L240-257 | GetConsoleOutputCP / SetConsoleOutputCP | 低:標準 Win32 API |
main.rs L262-263 | ntsort_main FFI 呼叫 | 中:C 函式呼叫,但參數有檢查 |
main.rs L297 | String::from_utf8_unchecked | 低:由 from_utf8_lossy 確認後才走此路徑 |
nthelpers.rs L12-13 | wcslen FFI | 低:標準 C runtime |
nthelpers.rs L41-52, L251-262 | RegGetValueW Registry 讀取 | 低:唯讀操作 |
nthelpers.rs L56-59 | GetCommandLineW 命令列讀取 | 低:標準 Win32 API |
評估:所有 unsafe 用法都是 Windows 平台 FFI 的必要模式,沒有任意記憶體操作或不受控的指標運算。
2. PowerShell 腳本 — 🟢 安全
pwsh-install.ps1:修改 PowerShell profile 檔案,使用 atomic write(先寫.new再 rename)- 無
Invoke-Expression、無iex、無動態程式碼執行 - 使用
Set-StrictMode -Version 2.0嚴格模式 - Registry 操作限於
HKLM:\SOFTWARE\Microsoft\coreutils自有路徑
3. C 程式碼 (ntsort) — 🟡 注意
deps/ntsort/sort.c共 2,498 行,為原生 Windows DOS sort 指令的相容實作- 使用
NDEBUG定義(停用 assert) - 為純本地排序工具,無網路操作
4. 網路呼叫 — 🟢 無
- 無
reqwest、hyper、TcpStream等網路依賴 - 無 HTTP client,不連外部服務
- 所有 URL 出現均為文件中的參考連結
5. 機密資料 — 🟢 未發現
- 無硬編碼密碼、API key、token
- 無
.env載入邏輯 - 無認證/授權相關程式碼
6. 供應鏈安全 — 🟢 良好
- 上游為知名開源專案(uutils),Microsoft 維護 fork
- 依賴均為成熟 Rust crate(clap, phf, textwrap, itertools)
- 使用 git submodule 鎖定上游版本
總結
| 類別 | 評級 | 說明 |
|---|---|---|
| 程式碼注入 | 🟢 | 無 eval/exec/動態執行 |
| 記憶體安全 | 🟡 | 12 處 unsafe(FFI 必要) |
| 網路安全 | 🟢 | 純離線工具 |
| 機密管理 | 🟢 | 無機密資料 |
| 供應鏈 | 🟢 | Microsoft 官方 + 成熟上游 |
| 權限 | 🟢 | 安裝需管理員,執行不需 |
第 7 章:FAQ(常見問題)
Q1: 與 WSL 有什麼不同?
WSL 執行完整 Linux kernel 與 userspace,佔用更多資源、需要 Hyper-V 支援。microsoft/coreutils 是原生 Windows binary,啟動速度更快、資源消耗更低,但僅提供 CLI 工具子集(無 systemd、無 apt、無 Linux-only API)。
Q2: 會破壞我的 Batch script 嗎?
不會——find 和 sort 使用啟發式分析 (heuristic analysis) 自動偵測 DOS 或 GNU 語法。若使用 /C、/I 等 DOS 旗標,會自動呼叫 DOS 相容版本。安裝時也可選擇預設行為。
Q3: PowerShell 的 ls 會被覆蓋嗎?
PowerShell 的 ls 是 Get-ChildItem 的 alias (別名)。安裝後透過 PSReadLine 整合處理衝突,但 Get-Command ls 仍會顯示 built-in。實際行為取決於 PATH 順序。
Q4: 支援 Windows 10 嗎?
是的,最低支援 Windows 10。但有一個已知問題:#49 回報 Windows 10 安裝失敗,可能與 GetTempPath2 API(Windows 11 新增)有關,PR #51 正在修復中。
Q5: 有哪些指令故意不包含?
kill(無 POSIX signals)、chmod/chown(POSIX-only 概念)、whoami(衝突 Windows 內建)、more/dir/expand(衝突 DOS 內建)。完整列表見 README 的 “Intentionally dropped” 段落。
Q6: 如何回報 Bug?
直接在 GitHub Issues 開 issue,或提交 PR。若 bug 在上游 uutils 中也存在,建議先到上游修復。
第 8 章:進階技巧
1. 透過 Registry 切換 find/sort 預設行為
1# 設定 find 預設為 GNU find(而非 DOS find)
2reg add "HKLM\SOFTWARE\Microsoft\coreutils" /v DefaultFind /t REG_DWORD /d 1 /f
3
4# 設定 sort 預設為 GNU sort
5reg add "HKLM\SOFTWARE\Microsoft\coreutils" /v DefaultSort /t REG_DWORD /d 1 /f
6
7# 還原為 DOS find/sort(值 = 0 或刪除)
8reg delete "HKLM\SOFTWARE\Microsoft\coreutils" /v DefaultFind /f
2. 處理 CRLF 問題
1# 移除 CR 字元,將 CRLF 轉為 LF
2cat file.txt | tr -d '\r' > unix_file.txt
3
4# uniq 前先正規化換行
5cat data.txt | tr -d '\r' | sort | uniq
3. 使用 multi-call binary 模式
1# 直接透過 coreutils.exe 呼叫
2coreutils ls -la
3coreutils grep -r "pattern" .
4coreutils find . -name "*.txt"
5
6# 列出所有可用指令
7coreutils --list
4. 建立自訂 alias
1# 在 PowerShell profile 中加入
2function ll { ls -lah @args }
3function la { ls -A @args }
4function grep { coreutils grep --color=auto @args }
5. 效能最佳化:善用 pipeline
1# 用 find + xargs 取代 foreach 迴圈,利用 parallel execution
2find . -name "*.log" -print0 | xargs -0 -P 4 grep -l "ERROR"
3
4# 避免不必要的 cat(Useless Use of Cat)
5# 不好:cat file.txt | grep "pattern"
6# 好: grep "pattern" file.txt
第 9 章:整合進其他工作流
與 PowerShell 混用
1# PowerShell cmdlet 的輸出 pipe 給 coreutils
2Get-Process | coreutils sort -k2 -rn
3
4# coreutils 輸出 pipe 給 PowerShell
5ls -la | Select-String "\.log$"
6
7# 注意:PowerShell 的 pipe 傳遞 .NET 物件
8# 而 coreutils 期望文字 stream,混用時注意編碼
與 VS Code 整合
在 VS Code 的 settings.json 中設定終端:
1{
2 "terminal.integrated.defaultProfile.windows": "PowerShell",
3 "terminal.integrated.env.windows": {
4 "PATH": "C:\\Program Files\\coreutils\\cmd;${env:PATH}"
5 }
6}
與 Makefile 搭配
1# Windows + coreutils 可直接使用 UNIX 語法的 Makefile
2SOURCES := $(shell find src/ -name "*.c")
3LOC := $(shell cat $(SOURCES) | wc -l)
4
5clean:
6 find . -name "*.o" -delete
7 rm -rf build/
與 Docker / Container 開發
1# 在 Windows host 上準備檔案、pipe 進 container
2find data/ -name "*.csv" -exec cat {} + | docker run -i python:3 python process.py
3
4# 比較 container 內外的檔案
5diff <(docker exec myapp cat /app/config.yml) config.yml
與 Git 整合
1# 搜尋 Git 歷史中的特定 pattern
2git log --all --oneline | grep "fix" | wc -l
3
4# 清理 untracked 檔案(結合 find)
5find . -name "*.pyc" -not -path "./.git/*" -delete
6
7# 產生變更統計
8git diff --stat | tail -1
第 10 章:重點摘要 Checklist
快速上手
- 安裝:
winget install Microsoft.Coreutils - 驗證:
coreutils --version顯示版本 - 列出指令:
coreutils --list - 測試基本指令:
ls -la、grep --version、find --version
核心概念
- 理解 multi-call binary (多重呼叫二進位) 架構
- 理解 find/sort 的 DOS/GNU 啟發式分流 (heuristic dispatch)
- 了解 Windows 特有注意事項(CRLF、NUL、路徑分隔符)
- 知道哪些指令被刻意排除及原因
日常使用
- 熟練檔案操作:
ls,cp,mv,rm,mkdir,touch - 熟練文字處理:
cat,head,tail,grep,sort,uniq,cut,tr,wc - 熟練搜尋:
find,xargs,grep -r - 熟練 pipeline 組合:
|,>,>>,2>NUL
進階
- 透過 Registry 設定 find/sort 預設行為
- 在 PowerShell profile 設定自訂 alias
- 整合進 CI/CD pipeline
- 處理 CRLF 換行問題
注意事項
- PowerShell 7.4+ 才支援(舊版不支援)
- 安裝需管理員權限,使用不需要
- Preview 狀態,可能有 breaking changes
- 建立 symlink 需 Developer Mode 或提權
第 11 章:進一步閱讀
官方資源
- GitHub 首頁 — 原始碼、Issue tracker、Release
- CONTRIBUTING.md — 貢獻指南與 repo 結構說明
- Release Page — 下載安裝檔
上游專案
- uutils/coreutils — GNU coreutils 的 Rust 重寫(上游主體)
- uutils/findutils — find + xargs 的 Rust 重寫
- uutils/grep — grep 的 Rust 重寫
相關技術
- Rust 程式語言 — 專案主要語言
- WinGet — Windows 套件管理器
- PSReadLine — PowerShell 命令列編輯模組
- phf crate — Perfect Hash Function,用於零成本查表
替代方案比較
| 方案 | 類型 | 優點 | 缺點 |
|---|---|---|---|
| microsoft/coreutils | 原生 binary | 輕量、快速、DOS 相容 | Preview、指令子集 |
| WSL | Linux 子系統 | 完整 Linux | 資源開銷、需 Hyper-V |
| Cygwin | 相容層 | 最完整 | 安裝大、效能損耗 |
| Git Bash | MSYS2 子集 | 隨 Git 安裝 | 指令有限 |
| BusyBox-w32 | 原生 binary | 極小 | 功能受限、無 grep/find |
| GnuWin32 | 原生 binary | 穩定 | 老舊、不再維護 |
Comments