简介:Linux(CentOS)环境下,开发或运维人员经常需要以目录树结构快速浏览文件层级,tree 命令正是解决这一需求的常用工具。这款压缩包内包含 tree-1.7.0 的完整源码和说明文档,既支持在离线或内网环境直接编译部署,也能帮助用户理解递归目录列表功能是如何用 C 语言实现的。压缩包内共有 19 个文件,其中 C 源码文件占 8 个,覆盖了核心逻辑、XML 与 JSON 输出等主要模块;其余文件包括 Makefile 构建脚本、安装指引、更新日志、许可协议、man 帮助手册及法语版手册等,方便使用者掌握安装流程和命令细节。整个压缩包仅 57KB,轻量便携,目前已有 4486 人学习下载,在系统运维、自动化脚本编写和 Linux 教学中都有参考价值。资源可直接用于 CentOS 等 Linux 发行版的编译部署,帮助用户快速获得简洁美观的目录树展示效果,无论是日常排查目录深度、梳理项目结构,还是编写自动化脚本时格式化输出,都能派上用场,尤其适合中初级 Linux 用户或对命令行工具实现方式感兴趣的开发者。
1. 从源码 tgz 装 tree:最小化服务器上绕不开的交付题
做过 Linux 环境交付的人都有种体验:一台刚初始化完的最小化服务器上,想看目录结构,敲 tree 却提示 command not found。然后要么去包管理器里碰运气,要么上网翻半天找一个能用的 tgz。tree 这个命令本身不大,可它偏偏不在默认安装列表里,很多生产环境的软件源还不一定收录。我就遇到过装 tree 装出编译报错的场景——因为最小化系统的 gcc 都是缺的,编译工具链断在半路,整台机器都得回头补依赖。这篇文章要记录的,就是用这份 tree 的 tgz 安装文件加配套使用说明,从零把环境搭起来的全过程。适合刚入门的开发者,也适合不想再被发行版包差异折腾的运维。装完你能自己验证命令生效,出了问题也知道往哪个方向排查。
2. 安装前准备:确认系统环境与拿到正确的 tree tgz 源码包
2.1 先检查系统环境和编译工具链:装 tree 前需要哪些依赖
tree 是 C 语言写的小工具,源码分发形态就是那个 tgz 包,没有现成的二进制可以拷过去直接用。除非你手动去别的机器上搬一个编译好的二进制,但那又引入 glibc 版本兼容的新问题,远不如从源码编译干净。所以动手之前,第一个要确认的是系统里有没有完整的编译工具链。
我习惯先敲三句:
gcc --version make --version tar --versiongcc 和 make 是编译和调度的核心,tar 是解压 tgz 必需的,三个命令都正常输出,说明基础环境没问题。如果 gcc 或 make 提示 command not found,就要先补工具链,不要带着缺依赖的状态去解压源码。apt 系系统我一般用apt -y install build-essential,yum 系系统用yum -y install gcc make,这属于补基础工具链,和任何源码安装都通用。
补工具链这一步还有个细节:编译需要 gcc 加上配套的 libc 开发头文件,如果系统里只有运行时库,编译阶段才会爆头文件缺失的错。与其等那时再补,不如在这一步把相关开发包一次性装齐。yum 系的 gcc 装完会带上 libgcc,但头文件还需要 glibc-devel 这类开发包,最省事的做法是在安装 gcc 时把常见的 devel 包一并带上。
还有一点容易被忽略:确认你的账号有没有 sudo 权限。make install 要把可执行文件写进系统目录,权限不够的话会在最后一步当场报错。提前用sudo -v验证一下 sudo 是否可用,能避免编译到头才翻车。
2.2 判断是否要自编译:tgz 包和预编译二进制的选择
tree 在很多发行版的软件源里都有收录,那为什么还要用 tgz 包自编译?这个问题的答案直接决定安装路线。软件源里有现成包时,直接装显然更快,但这种做法有几个前置问题:包管理器里的版本往往落后于上游;部分内网环境根本没有把 tree 同步进本地源;更麻烦的是,很多最小化交付镜像默认只带基础软件,软件源列表里压根找不到 tree。
与其依赖发行版仓库,不如直接持有 tgz 包。tree 官方分发的 tgz 包体积很小,整个编译过程在普通服务器上也就几秒钟,自编译的成本几乎可以忽略。带一个 tgz 包走,相当于掌握了在任何一台 Linux 机器上从零交付 tree 的能力。这就是自编译这条路线在交付场景里的真正价值:不依赖软件源、不依赖发行版差异,唯一要求就是那套编译工具链。
我自己的取舍标准是这样:个人开发机上如果软件源有 tree,直接装没问题;但凡是给服务器做交付,尤其是要写进交付脚本或者离线环境,一律走 tgz 自编译。后者的行为在所有机器上完全一致,不会出现这台有包、那台没包的尴尬。
2.3 tgz 包解压前检查:文件完整性、格式与目录结构
拿到 tgz 包之后不要急着解压,三步检查能避免一半以上的安装翻车。第一步看文件,第二步校验格式,第三步预览包内目录结构:
ls -l tree-*.tgz gzip -t tree-*.tgz && echo OK tar -tzf tree-*.tgz | head -20ls -l确认文件大小合理。tree 的源码包体积很小,几十 KB 到一两百 KB 都属于正常范围;如果文件小到只有几 KB,基本可以判断下载中断或者文件不对。gzip -t是 gzip 命令自带的完整性校验,命令成功并输出 OK 代表压缩流没有截断。tar -tzf里的-t是列表测试模式,只列出包内容不解出文件,加上-z处理 gzip 格式,-f指定文件名。
预览这一步能直接看到包内顶层目录名,比如 tree-xxx,后面 cd 进去时就不会打错路径。还能顺带确认包里的文件构成,tree 的 tgz 一般会把源码文件、README、LICENSE 放在一起,结构清爽。如果预览阶段就看到异样的路径层级或者凭空多出来的奇怪文件,这个包大概率来路不正,建议直接弃用。
2.4 工作目录规划:把源码放到哪里才不污染系统目录
源码编译的存放位置,直接影响后续维护和卸载。我习惯统一放到/usr/local/src,这是给用户自编译源码留的约定目录,和/usr/src(系统级源码)区分清楚。
sudo mkdir -p /usr/local/src sudo cp tree-*.tgz /usr/local/src/ cd /usr/local/src tar -zxvf tree-*.tgz cd tree-*/这五行分别负责建目录、拷包、切目录、解压、进入源码。mkdir -p在目录不存在时会自动创建,已存在时不会报错,在任何状态都能安全执行。我一般不把源码直接解压到 /tmp,因为 /tmp 会被系统定期清理,编译到一半目录消失的问题真实发生过。
另外,编译前看一眼/usr/local所在分区的剩余空间。tree 不占地方,但"编译前看磁盘水位"这个习惯很值钱,等到编译到没空间再回头清理,比一开始df -h /usr/local扫一眼要贵得多。
3. 编译安装 tree:从 tar 解压到 make install 的完整落地过程
3.1 解压 tgz 源码包并读懂 Makefile:prefix 和 CC 参数决定安装路径
真正的安装从解压开始。第 2 章的预览只是列清单,没有解出任何文件,这一步才正式解包:
tar -zxvf tree-*.tgz cd tree-*/-z让 tar 按 gzip 格式解压,-x解包,-v把解出的文件列到屏幕,-f指定文件名。这套参数是 tar 处理 tgz 最标准的写法,顺序不敏感,但-f后面必须紧跟文件名。cd tree-*/用通配符匹配目录名,我故意不手敲完整目录名,因为版本号容易打错。
解压进目录后,第一件事不是 make,而是读 Makefile:
head -30 Makefiletree 的 Makefile 结构很直白,顶部会定义几个关键的编译变量。prefix决定最终安装根目录,bindir、mandir 这些子路径全都跟着它走。常见的默认 prefix 是/usr,装完可执行文件落在/usr/bin,man 手册页落在/usr/share/man/man1。如果你希望装进/usr/local或者用户目录,必须在 make 阶段重新指定,这是整个安装过程里最需要提前想清楚的参数。
CC指定编译器,默认 gcc;CFLAGS是传给 gcc 的参数集。这两个一般不用动,但读一遍有个好处:你能看到这个包有没有用特殊编译选项,比如是否需要额外的头文件路径。我的习惯是只看 prefix 和 CC 两行,小工具不需要像大项目那样把 Makefile 逐行考古。
3.2 执行编译:make 的过程中发生了什么
环境确认、Makefile 读完,可以执行编译了:
makemake 会读取 Makefile 里的规则,调用 gcc 把 tree 的 C 源码编译成目标文件,再链接成可执行文件。整个过程的输出会依次出现 cc 的编译命令行,最后一条通常是cc ... -o tree。看到-o tree这条出现且没有报错,说明编译和链接两个阶段都走通了。
编译失败的时候,最忌讳盯着满屏日志情绪化。正确做法是停在第一条error:或fatal error:上。如果是缺头文件,看那行的路径提示;如果是语法层面的错误,就要考虑源码包和 gcc 版本的兼容性。我在实战里碰到的大多数是前者,后者在 tree 这种维护活跃的包上不常见。
机器核心多可以加速:
make -j4-j4让 make 最多同时跑 4 个编译任务。tree 这种单文件程序编译本来就快过一秒,-j在这里没有实际意义,但习惯从第一天保持下来,以后编译大型项目时收益很直观。注意,-j并行编译报错时日志次序会乱,排错时我会去掉-j单线程重跑,让错误行稳定出现在固定位置。
编译完成后在当前目录确认产物:
ls -l tree file treels -l看文件权限和属性,file tree看二进制的格式。两个命令一起跑,确认生成的是正常的 ELF 可执行文件,而不是零字节的空文件。
3.3 执行安装:make install 的路径、权限与安装产物清单
编译产物已经躺在源码目录里,下一步是放到系统可执行路径下:
sudo make installmake install是 Makefile 里的安装目标,它把编译好的 tree 复制到 prefix 指定目录,同时安装 man 手册页。sudo在这里基本是必须的,如果 prefix 是 /usr,写入 /usr/bin 和 /usr/share/man 都需要 root 权限。这一步会输出 install 相关命令,看到install ... /usr/bin/tree这类行,说明文件落位成功。
注意:
make install不改 prefix 的话默认写/usr,普通用户执行会在 install 阶段报权限错误。动手前先sudo -v确认权限,再决定走 sudo 还是自定义路径。
不想污染系统目录的选择是自定义 prefix:
make prefix=$HOME/.local install装完可执行文件在$HOME/.local/bin,全程不需要 root。这类装法的代价是要手动管理 PATH,$HOME/.local/bin不在 PATH 里的话,敲 tree 依然是 command not found。具体怎么配会在下一章的避坑清单里展开。
安装完成后,我用一套固定检查确认产物:
which tree tree --version man tree | head -5which tree回答命令能不能被系统找到,tree --version打印编译好的版本号,是安装成功的第一硬证据,man tree | head -5验证手册页落了位。三条全过,这一套 tgz 源码安装才算闭环。
4. 安装避坑:tree 的 tgz 编译安装最容易翻车的 5 个点
4.1 解压报错 "This does not look like a tar archive"
现象:执行tar -zxvf tree-*.tgz,终端直接提示This does not look like a tar archive,或者解压出来一堆乱码文件。
原因:文件在下载阶段被截断,或者拿到的根本不是 gzip 格式的 tar 包。部分下载渠道会把文件重复包装一层 gzip,也有站点返回的是纯 tar 格式但文件名仍写成 .tgz。
解决:先跑gzip -t,如果提示invalid compressed data,说明文件已损坏,删掉重新下载。如果 gzip 检查通过但 tar 还是报错,用file tree-*.tgz看真实格式,再按实际格式调整解压命令。我现在养成的习惯是下载后强制先gzip -t,再tar -tzf预览一次,这套检查能拦截九成以上的包损坏问题。
4.2 编译时提示 gcc 或 make 命令找不到
现象:敲 make 提示bash: make: command not found,或者gcc: command not found。刚初始化完的最小化服务器上很容易复现。
原因:系统没有安装基础编译工具链。发行版的最小化镜像默认不带开发工具,它在设计上就不打算让你现场编译。
解决:离开服务器当前环境,在能通的软件源上补装。apt 系跑apt -y install build-essential,yum 系跑yum -y install gcc make。装完重新执行gcc --version和make --version确认,再回来编译。内网离线环境没有本地源的话,这条补装路线很难走,建议提前把编译工具链或预编译好的 tree 二进制一并备好。这也是我在交付环境里坚持带 tgz 包走的原因。
4.3 make install 报权限拒绝
现象:提示install: cannot remove '/usr/bin/tree': Permission denied或cannot create regular file '/usr/bin/tree': Permission denied。
原因:/usr/bin 是 root 专属写的目录,普通用户执行 make install 必然触发权限错误。这台机器上没有 sudo,或者当前账号不在 sudoers 里。
解决:有 sudo 就sudo make install,没 sudo 就改走用户路径:
make prefix=$HOME/.local install装完后把export PATH="$HOME/.local/bin:$PATH"写进~/.bashrc,再source ~/.bashrc。这样不碰系统目录,又能正常使用。我现在所有没有 root 权限的机器,都会先确认 prefix 再决定装哪里,不在权限上硬碰。
4.4 编译时提示缺少头文件
现象:编译过程中报fatal error: stdio.h: No such file or directory,或者其他系统头文件找不到。
原因:系统里只有运行时库,没有对应开发头文件。普通桌面发行版会带全,服务器最小化安装时经常缺。这个坑比缺 gcc 更隐蔽,因为 gcc --version 可能已经显示正常,一编译才发现头文件不全。
解决:理解成"编译器有了,SDK 头文件缺了",用包管理器补开发库。apt 系是apt -y install libc6-dev,yum 系是yum -y install glibc-devel,补完重新 make。为了避免反复试错,我通常在装编译工具链时直接装整个开发包集合,头文件问题一次覆盖掉。
4.5 装完敲 tree 提示 command not found
现象:make install 已经成功,终端敲 tree 依然提示command not found。
原因:安装路径不在当前用户的 PATH 里。最常见的是用了prefix=$HOME/.local这类自定义路径,却没有加 PATH;也有装到了 /usr/local/bin,而你的 PATH 里没包含这个目录。
解决:先定位可执行文件在哪儿,再修正 PATH:
find /usr/local -name tree -type f 2>/dev/null echo $PATH看到文件在/usr/local/bin/tree而 PATH 里不含 /usr/local/bin 时,编辑~/.bashrc加上export PATH=/usr/local/bin:$PATH,然后 source。这类问题排查只要三分钟,但不少人卡在"装完了敲不出来"上直接怀疑编译失败。现在每台机器装完 tree,我第一件事就是which tree定位路径,这个动作已经固化进安装流程。
5. 配置与使用:tree 参数组合与真正能省时间的场景
5.1 基础参数搭配:-L、-d、-a 组合出最常见的目录报告
tree 的默认输出是递归列出所有子目录和文件。真正在运维场景里,很少有人裸敲 tree,都是按需求组合参数。最常用的一组是把目录深度、显示范围一次性定好:
tree -L 2 -d /usr/local tree -L 3 -a ~/project第一条只看 /usr/local 下两层目录,-d只显示目录不显示文件,适合快速梳理目录结构;第二条在项目目录里展开三层,-a把.git、.idea这种隐藏目录也带出来。两个参数一组合,等于生成一份"目录地图"。
这三个参数是 tree 的基础核心。-L后面必须跟数字表示深度,不加-L的默认行为是无限递归,遇到大目录会把终端刷到没法看。理解了-L限制深度、-d只看目录、-a包含隐藏文件,就能拼出九成以上的日常场景。我一般建议先只记这三个,其他参数遇到具体场景再查。
5.2 排除与匹配:-I、-P 处理大型项目里的噪音目录
在代码仓库里用 tree,最烦的是把 node_modules、dist、.git 这些目录完整列出来。仓库越大,输出越没法看。-I参数就是干这个的,指定要忽略的模式:
tree -L 3 -I 'node_modules|.git|dist|build' ~/project-I后面用引号圈住多个匹配模式,竖线分隔。这里必须用引号包起来,否则 shell 会把|当管道符处理,命令直接写裂。忽略模式支持通配符,比如-I '*node_modules*'也能匹配带路径的目录名。
提示:
-I的匹配模式必须用引号包裹,裸写-I node_modules|.git会被 shell 错误解析成管道。
与-I相对的是-P,只显示匹配的文件。比如只看 Python 文件在目录里的分布:
tree -P '*.py' -I '__pycache__' -L 2-P匹配文件名,-I排除目录,两个组合起来,既只看 .py 文件,又能把pycache这类自动生成目录屏蔽掉。注意-P的匹配只对文件生效,匹配到的路径上的目录也会一并显示,输出仍然是一棵完整目录树,只是文件被过滤了。这个搭配在梳理工程结构时几乎是标配。
5.3 输出控制:--charset、--noreport、-H 在脚本和网页场景中的细节
tree 的输出默认带树形符号,这些符号在不同字符集下显示效果完全不同。SSH 连上去输出乱码,或者树形线变成方块,多半是字符集没对齐。解决办法是显式指定字符集:
tree --charset utf-8 -L 2 /etc--charset utf-8明确告诉 tree 用 UTF-8 的树形符号,在现在的常用系统和 SSH 终端里基本通吃。
如果报告要交给脚本解析,加上--noreport能去掉最底部的目录数和文件数统计行:
tree -L 2 -d --noreport /usr--noreport让输出只剩目录树本身。脚本里需要干净输出时这个参数很关键,否则多出的统计行会让wc -l或 grep 的结果多一条,真排查起来容易懵。
脚本场景里还有两个常用参数:-i不要缩进线条,输出每一项单独一行,配grep、sed处理非常顺手;-f打印完整路径前缀,方便把结果直接喂给别的命令。这两个加上-x(不跨文件系统)和-F(目录加 / 后缀)基本覆盖了脚本化的大多数需求。
tree 还有一个容易被忽略的能力:直接用-H生成 HTML 目录树。指定基础路径后,输出就是一段可独立打开的网页,我在交付文档里给项目目录生成索引时用过,比手动写目录清单省力得多。先把--charset和--noreport这两个基础项定住,再按场景叠加-F、-x、-H,tree 就从"看目录"的小工具升级成能进脚本、能出网页的目录输出组件。
6. 装完怎么验证跑通:一套能复用的 tree 安装自检流程
装完 tree 之后,验证不能只敲一句tree --version就收工。我每次交付前会按下面三步固定走一遍,顺序不变,把"装没装对"和"能不能用"两个问题分开判断。
第一步,用 which 和版本信息确认路径与版本:
which tree tree --versionwhich 回答命令从哪里来,--version 回答编译出来的版本是否可用。两条过了,说明可执行文件的安装路径已经在 PATH 里。如果 which 没有任何输出,优先怀疑 PATH 没配上,而不是重新编译一遍。
第二步,在一个真实目录上做输出验证:
tree -L 1 /etc tree -L 2 /usr/local --charset utf-8第一条验证基础递归输出,第二条验证深度限制和字符集参数。这两条在真实路径上跑通,说明 tree 不是只有版本号,而是真的能和文件系统正常交互。我会顺带看下输出的 report 统计行是否正常,确认默认行为符合预期。
第三步,验证 man 手册是否就位:
man tree | head -5能翻出手册页,说明 install 阶段连文档都落了位;翻不出只影响查参数,不影响命令本身,可以后面再补。三组命令全部有输出,这套 tree 的 tgz 安装才算彻底跑通。
这些验证步骤看起来基础,但每次都跑一遍的价值在于把"安装成功"和"安装可用"划清界限。装完只看到编译通过就收工的教训我踩过不止一次,结果都是在真正要用的场景里才发现 PATH 没配、参数版本不对。现在每台机器装完 tree,我都强制走一遍 which、目录输出、man 三连,跑完再交给下一个环节。整套流程省掉的,是一次次远程上去"咦怎么不行"的排查时间。希望帮到你。
本文还有配套的精品资源,点击获取