tre 在 HarmonyOS 上的构建与适配
本文介绍了现代化目录树工具tre的核心特性与使用场景。tre作为传统tree命令的Rust替代方案,具有智能文件过滤、颜色高亮、编辑器别名等特性,支持JSON输出和跨平台运行。文章详细说明了安装配置、常见问题解决方法,并重点阐述了适配开源鸿蒙PC端的要点,包括系统环境差异处理、Rust工具链的交叉编译配置等。最后提供了构建脚本和HNP包配置说明,帮助开发者将tre集成到鸿蒙生态中。
目录
工具简介
tre 是一个现代化的 tree 命令替代工具,使用 Rust 语言开发。它提供了比传统 tree 命令更强大的功能和更好的用户体验。
什么是 tre?
tre 是一个命令行工具,用于以树状图的形式展示目录结构。它的名字来源于 “tree”(树),但提供了更多现代化的特性。
核心特性
-
智能文件过滤:
- 自动跳过
.gitignore中指定的文件 - 支持正则表达式模式排除
- 可以只显示目录或特定类型的文件
- 自动跳过
-
颜色高亮:
- 支持
LS_COLORS环境变量 - 根据文件类型自动着色
- 终端友好的输出格式
- 支持
-
编辑器别名功能:
- 为每个文件创建快捷别名
- 快速打开文件进行编辑
- 支持自定义编辑器命令
-
多种输出格式:
- 传统的树状图输出
- JSON 格式输出(
-j选项) - 可限制目录深度
-
跨平台支持:
- 支持 Linux、macOS、Windows
- 单一可执行文件,零运行时依赖
- 无需额外配置即可使用
开发语言与设计优势
Rust 语言的优势:
- 性能:编译后的二进制文件运行速度快,内存占用低
- 安全性:内存安全保证,避免常见的内存错误
- 可移植性:单一可执行文件,易于分发和部署
- 现代特性:支持异步、模式匹配等现代编程特性
设计优势:
- 零依赖:编译后是单个可执行文件,不需要额外的库
- 快速启动:启动速度快,适合频繁使用
- 资源占用低:内存和 CPU 占用小
- 易于集成:可以轻松集成到脚本和工具链中
核心用途与场景
基本用法
1. 查看当前目录结构
# 查看当前目录
tre
# 查看指定目录
tre /path/to/directory
# 显示所有文件(包括隐藏文件)
tre -a
2. 筛选特定类型文件
# 只显示目录
tre -d
# 排除特定模式的文件
tre -E "\.(o|a|so)$" # 排除编译产物
# 只显示 Rust 源文件(配合 grep)
tre | grep "\.rs$"
3. 限制目录深度
# 只显示 2 层深度
tre -l 2
# 查看项目顶层结构
tre -l 1
4. JSON 输出
# 输出 JSON 格式,便于脚本处理
tre -j > structure.json
# 配合 jq 进行进一步处理
tre -j | jq '.[] | select(.type == "file") | .name'
5. 编辑器别名功能
# 启用编辑器别名
tre -e
# 使用自定义编辑器
tre -e vim
# 配置 shell 别名(在 ~/.bashrc 或 ~/.zshrc 中)
tre() { command tre "$@" -e && source "/tmp/tre_aliases_$USER" 2>/dev/null; }
使用后,每个文件前会显示一个数字,输入 e数字 即可打开对应文件。
实际应用场景
场景 1:快速查看项目结构
# 查看 Rust 项目的结构
tre -l 3
# 输出示例:
# .
# ├── Cargo.toml
# ├── src/
# │ ├── main.rs
# │ └── lib.rs
# └── tests/
# └── integration_test.rs
场景 2:配合管道命令
# 导出目录结构到文件
tre > project_structure.txt
# 统计文件数量
tre | grep -c "├──\|└──"
# 查找特定文件
tre | grep "config"
场景 3:CI/CD 集成
# 在 CI 中生成项目结构文档
tre -j > docs/structure.json
# 验证项目结构是否符合规范
tre -d | grep -q "src" && echo "Structure OK" || echo "Missing src directory"
对比传统 tree 命令的优势
| 特性 | tree | tre |
|---|---|---|
| Git 忽略支持 | ❌ | ✅ |
| 编辑器别名 | ❌ | ✅ |
| JSON 输出 | ❌ | ✅ |
| 正则过滤 | 有限 | ✅ |
| 性能 | 中等 | 高 |
| 跨平台 | 需要编译 | 单一二进制 |
| 颜色支持 | 基础 | 完整 LS_COLORS |
常见报错与解决方案
问题 1:安装失败
错误信息:
error: failed to compile `tre-command`
原因:Rust 工具链未正确安装或版本过旧。
解决方案:
# 安装 Rust(如果未安装)
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
# 更新 Rust 工具链
rustup update stable
# 验证安装
rustc --version
cargo --version
问题 2:运行时权限错误
错误信息:
Permission denied: /path/to/directory
原因:没有读取目录的权限。
解决方案:
# 检查目录权限
ls -ld /path/to/directory
# 使用 sudo(如果需要)
sudo tre /path/to/directory
# 或者修改目录权限(谨慎使用)
chmod +r /path/to/directory
问题 3:目录路径解析异常
错误信息:
No such file or directory: /path/to/directory
原因:路径不存在或路径格式错误。
解决方案:
# 检查路径是否存在
ls -la /path/to/directory
# 使用绝对路径
tre /home/user/project
# 使用相对路径
cd /home/user/project
tre .
问题 4:颜色显示异常
错误信息:终端中颜色显示不正确或没有颜色。
原因:终端不支持颜色或 LS_COLORS 未设置。
解决方案:
# 强制启用颜色
tre -c always
# 禁用颜色
tre -c never
# 设置 LS_COLORS(Linux)
eval $(dircolors -b)
# 检查终端是否支持颜色
echo $TERM
问题 5:编辑器别名不工作
错误信息:输入 e数字 后没有反应。
原因:Shell 配置未正确设置。
解决方案:
# 检查 shell 配置
cat ~/.bashrc | grep tre
cat ~/.zshrc | grep tre
# 添加配置(Bash/Zsh)
echo 'tre() { command tre "$@" -e && source "/tmp/tre_aliases_$USER" 2>/dev/null; }' >> ~/.bashrc
# 重新加载配置
source ~/.bashrc
# 手动加载别名文件
source /tmp/tre_aliases_$USER
问题 6:编译时依赖问题
错误信息:
error: failed to resolve: use of undeclared crate or module
原因:依赖版本不兼容或 Cargo.lock 过期。
解决方案:
# 更新依赖
cargo update
# 清理并重新构建
cargo clean
cargo build --release
# 检查 Cargo.toml 中的依赖版本
cat Cargo.toml
适配开源鸿蒙 PC 端的要点
系统环境差异
1. 包管理器
HarmonyOS PC 使用 HNP(HarmonyOS Native Package)作为包管理格式,而不是传统的 apt、yum 或 brew。
影响:
- 需要创建 HNP 包配置文件(
hnp.json) - 安装路径遵循 HNP 规范
- 包管理命令不同
2. 依赖库
HarmonyOS 使用 musl libc 而不是 glibc,这影响:
- 链接方式:需要使用静态链接或 musl 兼容的动态链接
- 系统调用:某些系统调用可能不同
- 库依赖:需要确保所有依赖都支持 musl
3. 终端交互兼容性
HarmonyOS 终端可能使用不同的:
- 颜色支持:需要测试 LS_COLORS 兼容性
- 字符编码:确保 UTF-8 支持
- 终端特性:某些高级特性可能需要适配
Rust 工具链在鸿蒙上的编译适配
1. 目标平台选择
HarmonyOS 使用 aarch64-unknown-linux-musl 作为目标平台:
export TARGET=aarch64-unknown-linux-musl
原因:
- HarmonyOS 基于 Linux 内核
- 使用 musl libc 而不是 glibc
- 架构是 aarch64(ARM 64位)
2. 交叉编译配置
需要配置 Rust 工具链使用 HarmonyOS SDK:
# 设置工具链环境变量
export CC_aarch64_unknown_linux_musl=${CC}
export CXX_aarch64_unknown_linux_musl=${CXX}
export AR_aarch64_unknown_linux_musl=${AR}
export RANLIB_aarch64_unknown_linux_musl=${RANLIB}
export STRIP_aarch64_unknown_linux_musl=${STRIP}
3. 链接器配置
需要配置 .cargo/config.toml 使用 HarmonyOS 的链接器:
[target.aarch64-unknown-linux-musl]
linker = "clang"
rustflags = [
"-C", "link-arg=--target=aarch64-linux-ohos",
"-C", "link-arg=--sysroot=${SDK_PATH}/native/sysroot",
"-C", "link-arg=-fuse-ld=lld",
"-C", "link-arg=--ld-path=${SDK_PATH}/native/llvm/bin/ld.lld",
]
关键适配要点总结
- 目标平台:使用
aarch64-unknown-linux-musl - 链接器:使用 HarmonyOS SDK 的 LLD
- 系统根目录:指定 HarmonyOS SDK 的 sysroot
- 包格式:使用 HNP 格式打包
- 安装路径:遵循 HNP 规范
鸿蒙适配中的报错解决过程
报错 1:构建系统识别错误
错误信息:
make: *** No rule to make target `clean'. Stop.
make: *** No targets specified and no makefile found. Stop.
原因分析:
tre 是一个 Rust 项目,使用 Cargo 作为构建系统,而不是 Makefile。原始的构建脚本错误地使用了 make 命令。
解决过程:
-
识别构建系统:
ls -la # 发现 Cargo.toml,确认是 Rust 项目 -
修改构建脚本:
- 移除
make clean、make VERBOSE=1、make install命令 - 改用
cargo build --release --target ${TARGET}
- 移除
-
配置交叉编译:
- 设置目标平台为
aarch64-unknown-linux-musl - 配置工具链环境变量
- 创建
.cargo/config.toml
- 设置目标平台为
最终解决方案:
# 使用 Cargo 构建
cargo build --release --target aarch64-unknown-linux-musl
报错 2:链接器选项不兼容
错误信息:
ld: unknown option: --as-needed
clang-15: error: linker command failed with exit code 1
原因分析:
Rust 默认会添加 -Wl,--as-needed 链接器选项,但 HarmonyOS SDK 使用的 LLD 链接器不支持这个选项。
排查思路:
-
检查链接器类型:
file ${SDK_PATH}/native/llvm/bin/ld.lld # 确认是 LLD 链接器 -
查看 Rust 传递的参数:
cargo build --release --target ${TARGET} --verbose 2>&1 | grep "link-arg" # 发现 -Wl,--as-needed 选项 -
尝试禁用选项:
- 在
rustflags中添加-Wl,--no-as-needed(无效) - Rust 仍然会添加
--as-needed
- 在
解决方案:
创建链接器包装脚本,过滤掉不支持的选项:
# 创建链接器包装脚本
LINKER_WRAPPER=$(mktemp)
cat > "${LINKER_WRAPPER}" << 'EOF'
#!/bin/bash
ARGS=()
for arg in "$@"; do
case "$arg" in
*--as-needed*)
# 跳过不支持的选项
;;
*)
ARGS+=("$arg")
;;
esac
done
exec "${CC}" "${ARGS[@]}"
EOF
chmod +x "${LINKER_WRAPPER}"
# 在 .cargo/config.toml 中使用包装脚本
linker = "${LINKER_WRAPPER}"
关键代码:
# 过滤掉 --as-needed 相关选项
case "$arg" in
*--as-needed*)
# 跳过
;;
-Wl,--as-needed)
# 跳过
;;
-Wl,--no-as-needed)
# 也跳过(LLD 不支持)
;;
*)
ARGS+=("$arg")
;;
esac
报错 3:目标平台配置错误
错误信息:
error[E0463]: can't find crate for `std`
= note: the `aarch64-apple-darwin` target may not be installed
原因分析:
Rust 尝试为当前主机平台(macOS)编译,而不是为目标平台(HarmonyOS)编译。
解决过程:
-
检查目标平台:
rustup target list | grep aarch64 # 确认 aarch64-unknown-linux-musl 存在 -
安装目标平台:
rustup target add aarch64-unknown-linux-musl -
确保使用正确的目标:
cargo build --release --target aarch64-unknown-linux-musl
最终解决方案:
export TARGET=aarch64-unknown-linux-musl
cargo build --release --target ${TARGET}
报错 4:安装路径错误
错误信息:
cp: directory /Users/jianguo/HarmonyOSPC/build/data/service/hnp//tre.org/tre_1.0.0 does not exist
原因分析:
安装目录不存在,需要先创建。
解决方案:
# 创建安装目录
mkdir -p ${TREE_INSTALL_HNP_PATH}/usr/bin
mkdir -p ${TREE_INSTALL_HNP_PATH}/usr/share/man/man1
适配过程中的关键决策
- 使用链接器包装脚本:解决 LLD 不支持的选项问题
- 静态链接优先:减少运行时依赖
- 遵循 HNP 规范:确保包格式正确
- 错误处理完善:添加详细的错误检查和提示
构建脚本详解
build_ohos.sh 完整代码
export TREE_INSTALL_HNP_PATH=${HNP_PUBLIC_PATH}/tre.org/tre_1.0.0
# 创建安装目录
mkdir -p ${TREE_INSTALL_HNP_PATH}/usr/bin
mkdir -p ${TREE_INSTALL_HNP_PATH}/usr/share/man/man1
# 设置 Rust 交叉编译目标
export CARGO_TARGET_DIR=${PWD}/target
export TARGET=aarch64-unknown-linux-musl
# 配置 cargo 使用 HarmonyOS 工具链
export CC_aarch64_unknown_linux_musl=${CC}
export CXX_aarch64_unknown_linux_musl=${CXX}
export AR_aarch64_unknown_linux_musl=${AR}
export RANLIB_aarch64_unknown_linux_musl=${RANLIB}
export STRIP_aarch64_unknown_linux_musl=${STRIP}
# 设置链接器
export CARGO_TARGET_AARCH64_UNKNOWN_LINUX_MUSL_LINKER=${CC}
# 创建 .cargo 配置目录
mkdir -p .cargo
# 创建链接器包装脚本
LINKER_WRAPPER=$(mktemp)
cat > "${LINKER_WRAPPER}" << LINKER_EOF
#!/bin/bash
ARGS=()
for arg in "\$@"; do
case "\$arg" in
*--as-needed*)
;;
-Wl,--as-needed)
;;
-Wl,--no-as-needed)
;;
*)
ARGS+=("\$arg")
;;
esac
done
exec "${CC}" "\${ARGS[@]}"
LINKER_EOF
chmod +x "${LINKER_WRAPPER}"
# 动态生成 .cargo/config.toml
SDK_PATH=${OHOS_SDK:-/Users/jianguo/Desktop/ohosdk}
cat > .cargo/config.toml << EOF
[target.aarch64-unknown-linux-musl]
linker = "${LINKER_WRAPPER}"
rustflags = [
"-C", "link-arg=--target=aarch64-linux-ohos",
"-C", "link-arg=--sysroot=${SDK_PATH}/native/sysroot",
"-C", "link-arg=-fuse-ld=lld",
"-C", "link-arg=--ld-path=${SDK_PATH}/native/llvm/bin/ld.lld",
]
EOF
# 构建 release 版本
cargo build --release --target ${TARGET} --verbose
# 安装二进制文件
cp ${CARGO_TARGET_DIR}/${TARGET}/release/tre ${TREE_INSTALL_HNP_PATH}/usr/bin/tre
chmod +x ${TREE_INSTALL_HNP_PATH}/usr/bin/tre
# 复制 man pages
if [ -f manual/tre.1 ]; then
cp manual/tre.1 ${TREE_INSTALL_HNP_PATH}/usr/share/man/man1/
fi
# 复制 hnp.json 并打包
cp hnp.json ${TREE_INSTALL_HNP_PATH}/
pushd ${TREE_INSTALL_HNP_PATH}/../
${HNP_TOOL} pack -i ${TREE_INSTALL_HNP_PATH} -o ${ARCHIVE_PATH}/
tar -zvcf ${ARCHIVE_PATH}/ohos_tre_1.0.0.tar.gz tre_1.0.0/
popd
脚本关键点解析
1. 链接器包装脚本
作用:过滤掉 LLD 不支持的 --as-needed 选项。
实现:
- 遍历所有链接器参数
- 过滤掉包含
--as-needed的参数 - 将剩余参数传递给实际链接器
2. Cargo 配置
.cargo/config.toml:
- 指定链接器为包装脚本
- 配置 HarmonyOS SDK 路径
- 设置链接器参数
3. 构建流程
- 清理:
cargo clean - 构建:
cargo build --release --target ${TARGET} - 安装:复制二进制文件和文档
- 打包:创建 HNP 包和 tar 归档
HNP 包配置
hnp.json
{
"type": "hnp-config",
"name": "tre",
"version": "1.0.0",
"install": {}
}
安装目录结构
tre_1.0.0/
├── usr/
│ ├── bin/
│ │ └── tre # 可执行文件
│ └── share/
│ └── man/
│ └── man1/
│ └── tre.1 # 用户手册
└── hnp.json # HNP 包配置
构建结果
构建成功后,会生成以下文件:
-
HNP 包:
tre.org_tre_1.0.0.hnp- HarmonyOS 原生包格式
- 可以直接安装到 HarmonyOS 设备
-
Tar 归档:
ohos_tre_1.0.0.tar.gz- 压缩的 tar 归档
- 包含完整的安装目录结构
构建输出示例
==========================================
Build completed successfully!
==========================================
HNP Package: /path/to/archive/tre.org_tre_1.0.0.hnp
Tar Archive: /path/to/archive/ohos_tre_1.0.0.tar.gz
Installation Path: /path/to/data/service/hnp/tre.org/tre_1.0.0
==========================================
仓库地址与安装方式
仓库地址
HarmonyOS 适配版本:
- 仓库:https://gitcode.com/nutpi/tre
- Tag:
1.0.0_ohos - 原始项目:https://github.com/dduan/tre
安装方式
Linux(通用)
使用 Cargo:
cargo install tre-command
使用包管理器:
# Debian/Ubuntu
sudo apt install tre-command
# Arch Linux (AUR)
yay -S tre-command
从源码编译:
git clone https://github.com/dduan/tre.git
cd tre
cargo build --release
sudo cp target/release/tre /usr/local/bin/
macOS
使用 Homebrew:
brew install tre-command
使用 MacPorts:
sudo port install tre-tree
使用 Cargo:
cargo install tre-command
Windows
使用 Scoop:
scoop install tre-command
使用 Windows Package Manager:
winget install tre-command
使用 Cargo:
cargo install tre-command
开源鸿蒙 PC
使用 HNP 包:
# 安装 HNP 包
hnp install tre.org_tre_1.0.0.hnp
# 或使用 tar 归档
tar -xzf ohos_tre_1.0.0.tar.gz
# 手动复制到系统路径
从源码交叉编译:
# 1. 克隆仓库
git clone https://gitcode.com/nutpi/tre.git
cd tre
git checkout 1.0.0_ohos
# 2. 设置 HarmonyOS SDK 路径
export OHOS_SDK=/path/to/ohosdk
# 3. 运行构建脚本
./build_ohos.sh
# 4. 安装生成的 HNP 包
hnp install tre.org_tre_1.0.0.hnp
验证安装
# 检查版本
tre --version
# 测试基本功能
tre
# 查看帮助
tre --help
总结
适配要点
- 构建系统识别:Rust 项目使用 Cargo,不是 Makefile
- 目标平台选择:使用
aarch64-unknown-linux-musl - 链接器兼容性:使用包装脚本过滤不支持的选项
- 工具链配置:正确配置交叉编译环境变量
- 包格式:遵循 HNP 规范
关键决策
- 链接器包装脚本:解决 LLD 不支持的选项问题
- 动态配置生成:根据 SDK 路径生成
.cargo/config.toml - 错误处理:添加详细的错误检查和提示
优势
- 零运行时依赖:单一可执行文件,部署简单
- 高性能:Rust 编译,运行速度快
- 功能强大:支持 Git 忽略、编辑器别名等高级特性
- 易于集成:可以轻松集成到脚本和工具链中
适用场景
- 项目结构可视化
- 文档生成
- CI/CD 集成
- 开发工具集成
- 文件管理辅助
FAQ
Q1: tre 和 tree 有什么区别?
A: tre 是 tree 的现代化替代品,主要区别:
- tre 支持 Git 忽略文件
- tre 提供编辑器别名功能
- tre 支持 JSON 输出
- tre 性能更好,启动更快
- tre 是单一二进制文件,无需额外依赖
Q2: 为什么选择 Rust 开发?
A: Rust 的优势:
- 内存安全,避免常见错误
- 性能接近 C/C++
- 单一可执行文件,易于分发
- 跨平台支持好
- 现代语言特性丰富
Q3: 编辑器别名功能如何工作?
A: tre 会:
- 为每个文件分配一个数字
- 创建 shell 别名(如
e1、e2) - 将别名保存到临时文件
- Shell 配置会加载这些别名
- 输入
e数字即可打开对应文件
Q4: 如何在 HarmonyOS 上使用 tre?
A:
- 安装 HNP 包:
hnp install tre.org_tre_1.0.0.hnp - 或从源码交叉编译
- 使用方式与 Linux 相同
Q5: 链接器包装脚本是必需的吗?
A: 是的,因为:
- HarmonyOS SDK 使用 LLD 链接器
- LLD 不支持
--as-needed选项 - Rust 默认会添加这个选项
- 包装脚本可以过滤掉不支持的选项
Q6: 如何自定义编辑器?
A:
# 使用环境变量
export EDITOR=vim
tre -e
# 或直接指定
tre -e vim
tre -e code # VS Code
Q7: 可以只显示特定类型的文件吗?
A: 可以配合其他工具:
# 只显示 .rs 文件
tre | grep "\.rs$"
# 排除特定模式
tre -E "\.(o|a|so)$"
Q8: JSON 输出格式是什么?
A: JSON 输出是一个数组,每个元素包含:
name: 文件/目录名type: “file” 或 “directory”path: 完整路径children: 子项(如果是目录)
相关链接
更多推荐



所有评论(0)