第 2 章 · 06 文件名的拆解:`basename`、`dirname`、`tree`


第 2 章 · 06 文件名的拆解:basename、dirname、tree

本节摘要:本章的收尾节,讲三个「小而美」的工具。basename 和 dirname 负责把一个完整路径拆成「文件名」和「目录部分」——这俩在 Shell 脚本里几乎天天用(比如从 /a/b/c.txt 取出 c.txt 或 /a/b)。tree 则把目录结构画成树形,是调试与文档的利器。它们单独看都简单,但理解它们的用法,能让你在写脚本时少走很多弯路。本节也会顺带把本章「文件与目录」的知识做一个简短回顾,为下一章「文本处理」做衔接。

内容来源:原项目「Linux 命令大全」command/basename.md、command/dirname.md、command/tree.md,精选并套用体系化模板。

学习目标

阅读完本节,你应当能够:

  1. 用 basename 从完整路径取出文件名部分,并能去掉指定扩展名。
  2. 用 dirname 从完整路径取出目录部分。
  3. 理解两者在 Shell 脚本里的典型场景(批量改名、拼接路径)。
  4. 用 tree 以树形可视化目录结构,掌握 -L(深度)、-a(含隐藏)、-d(只看目录)、-h(带大小)等选项。
  5. 综合运用 basename/dirname/tree 解决脚本里的路径处理需求。

一、设计动机:脚本里为什么常要拆路径

写 Shell 脚本时,你常会拿到一个完整路径(比如遍历文件得到的 /data/logs/app.log),却只想要其中一部分:有时要文件名(app.log),有时要目录(/data/logs),有时要不带扩展名的名字(app)。如果靠 awk -F'/' 或 sed 去拆,既啰嗦又易错。

basename 和 dirname 就是为这个需求设计的专用工具——它们正确处理路径的各种边界情况(尾随斜杠、多层目录、空扩展名),让你一行搞定。它们的本质是对路径字符串做「按最后一个斜杠切分」:

路径: /data/logs/app.log ↑ 最后一个斜杠 dirname 部分: /data/logs (斜杠左边) basename 部分: app.log (斜杠右边) ​

二、高频组合与实战

basename:取文件名

basename /a/b/c.txt # 输出 c.txt basename /a/b/c.txt .txt # 输出 c (去掉指定后缀) basename /a/b/c.txt .log # 输出 c.txt (后缀不匹配, 原样输出) basename /a/b/ # 输出 b (尾随斜杠被忽略) ​

dirname:取目录部分

dirname /a/b/c.txt # 输出 /a/b dirname /a/b/ # 输出 /a (尾随斜杠被忽略, 取倒数第二级) dirname c.txt # 输出 . (没有目录部分时给当前目录) ​

典型脚本场景

# 批量给 .txt 文件加 .bak 后缀 for f in *.txt; do name=$(basename "$f" .txt) # 去掉 .txt, 得到纯名字 cp "$f" "${name}.txt.bak" # 拼出备份文件名 done # 从完整路径得到"父目录 + 新文件名" path=/data/logs/app.log dir=$(dirname "$path") # /data/logs newname=$(basename "$path" .log).csv # app.csv echo "$dir/$newname" # /data/logs/app.csv ​

tree:目录结构可视化

tree # 当前目录的树形结构 tree -L 2 # 只看 2 层深度(大目录必备) tree -d # 只看目录, 不显示文件 tree -a # 含隐藏文件(点开头) tree -h # 带文件大小 tree -L 2 -d --dirsfirst # 目录优先排前 ​

示例输出:

$ tree -L 2 . ├── docs │ ├── guide.md │ └── api.md ├── src │ ├── main.py │ └── utils.py └── README.md ​

💡 技巧:tree 默认可能没装(apt install tree 或 yum install tree)。装上后,它比 ls -R 的输出直观得多,特别适合在文档里展示项目结构。

三、踩坑与排错

坑 1:basename 的后缀参数必须是「字面后缀」

basename photo.tar.gz .gz # 输出 photo.tar (只去掉 .gz) basename photo.tar.gz .tar.gz # 输出 photo (去掉 .tar.gz) ​

basename 的第二个参数不是正则,是字面字符串,只从末尾匹配一次。想去掉多层后缀,要么把完整后缀写全(.tar.gz),要么配合 sed。

坑 2:dirname 对纯文件名返回「.」

dirname "app.log" # 输出 . (当前目录) ​

这是个合理的「无目录则视为当前目录」的设计,但在脚本里拼接路径时要注意,. /new.log 不是合法路径。用 realpath 或 [ "$dir" = "." ] && dir=$(pwd) 处理。

坑 3:路径含空格时务必加引号

name=$(basename "/data/my file.txt") # 对, 加引号 name=$(basename /data/my file.txt) # 错! 会被拆成两个参数 ​

路径含空格是 Shell 脚本的头号坑。所有变量化的路径,在用 $var 时都加双引号:cp "$f" "${name}.bak"。

本节要点回顾

  1. basename 路径 取文件名部分;basename 路径 .后缀 可顺便去掉指定后缀(字面匹配,非正则)。
  2. dirname 路径 取目录部分;纯文件名(无斜杠)返回 .(当前目录)。
  3. 两者在脚本里高频出现:批量改名、拼接路径、提取名字做 key。
  4. tree 树形可视化目录:-L 限深度、-d 只看目录、-a 含隐藏、-h 带大小;比 ls -R 直观。
  5. 路径含空格务必加双引号:这是 Shell 脚本的头号坑,所有 $var 引用都该加引号。

至此第 2 章「文件与目录管理」全部讲完。本章从最朴素的 ls/cd 开始,一路讲到 i 节点与硬软链接——你现在已经能熟练操纵文件树,并理解了「文件是什么」的底层结构。下一章我们把视角从「文件本身」转到「文件里的文本」,进入全书最硬核的文本处理流水线。


作者与出处
原作者: 灏天文库
来源:jaywcjlove
许可证:MIT
整理: 灏天文库整理
由灏天文库结构化整理,提供目录导航、全文检索与在线阅读,便于系统化学习
发布者: 作者: 灏天文库 转发
评论区 (0)
U