zx 是一款强大的工具,它弥合了 shell 脚本与 JavaScript 之间的鸿沟,让你兼得两者的优势。它为 child_process 提供了便捷的封装,具备合理的默认值和跨平台兼容性,非常适合编写自动化脚本、部署工具和命令行实用程序。
为什么选择 zx?
传统的 shell 脚本在处理复杂逻辑时会变得繁琐,而 Node.js 在执行简单命令时又需要大量样板代码。zx 通过以下特性解决了这个问题:
- JavaScript 语法及其所有现代特性
- 内置实用程序用于常见 shell 操作
- 跨平台兼容性(Linux、macOS、Windows)
- 开箱即用的 TypeScript 支持
- 零样板代码执行命令
安装
选择你喜欢的安装方式:
| 方法 | 命令 | 描述 |
|---|---|---|
| npm | npm install zx | 标准 npm 安装 |
| global | npm install -g zx | 全局安装以供系统使用 |
| npx | npx zx script.js | 无需安装即可运行脚本 |
| yarn | yarn add zx | Yarn 包管理器 |
| pnpm | pnpm add zx | pnpm 包管理器 |
| bun | bun install zx | Bun 运行时支持 |
| deno | deno install -A npm:zx | Deno 运行时支持 |
对于轻量级脚本,可以考虑使用 zx@lite - 这是一个依赖更少、启动速度更快的精简版本。
你的第一个 zx 脚本
创建一个名为 script.mjs 的文件,并添加以下 shebang:
#!/usr/bin/env zx
// 你的第一个 zx 脚本
await $`echo "Hello, zx!"`
const name = "World"await $`echo "Hello, ${name}!"` // 并行运行多个命令
await Promise.all([ $`echo "Task 1"`, $`echo "Task 2"`, $`echo "Task 3"`])
使其可执行并运行:
chmod +x script.mjs./script.mjs
或者使用 zx CLI:
zx script.mjs
核心概念
使用 $ 执行命令
$ 模板字面量是你运行 shell 命令的主要工具:
// 基本命令执行const output = await $`ls -la` // 变量会自动转义和引用
const filename = "my file.txt"await $`touch ${filename}` // 同步执行
const currentDir = $.sync`pwd` // 数组参数
const flags = ["--oneline", "--decorate", "--color"]
await $`git log ${flags}`
进程输出处理
命令返回 ProcessOutput 对象,其中包含捕获的 stdout/stderr:
try {
const result = await $`git status`
console.log("Git status:", result.stdout)
} catch (error) {
console.log("Command failed:", error.exitCode)
console.log("Error output:", error.stderr)
}
内置实用程序
zx 包含了常用的实用程序,无需额外导入:
// 切换目录
cd('./my-project')
// 读写文件
const content = await fs.readFile('config.json', 'utf8')
await fs.writeFile('output.txt', 'Hello World')
// 获取数据
const response = await fetch('https://api.github.com/users/google')
const user = await response.json()
// 解析参数
const args = minimist(process.argv.slice(2))
console.log("Arguments:", args)
文件扩展名和模块类型
| 扩展名 | 模块类型 | 顶层 await | 推荐用于 |
|---|---|---|---|
.mjs | ESM | ✅ | 现代 JavaScript 脚本 |
.js | ESM/CJS | ❌ (需要包装器) | 传统兼容性 |
.ts | TypeScript | ✅ | 类型安全开发 |
对于 .js 文件,需要包装你的代码:
void async function () { await $`echo "Hello"`}()
为了获得更好的 IDE 自动补全功能,请显式导入全局变量:import 'zx/globals'