stat -c "%n" 输出完整路径而非纯文件名,正确提取 basename 应使用 basename 命令或 Bash 参数扩展 ${var##*/},二者更安全、可靠且符合 POSIX。

stat -c "%n" 并不是获取“纯名称”(即不带路径的文件名)的正确用法。它实际输出的是带完整路径的文件名,和 ls -d 或直接写路径效果类似,不是 basename。
要在自动化脚本中安全、可靠地提取文件的纯名称(basename),需明确区分几个概念,并选择合适工具:
✅ 正确理解 %n 的行为
stat -c "%n" /path/to/file.txt
→ 输出:/path/to/file.txt(完整路径,非纯名)
这不是 bug,而是设计如此:%n 表示 “file name”,即 stat 命令接收到的原始路径字符串。
✅ 获取纯名称(basename)的推荐方法
1. 用 basename 命令(最直观、可读性强)
basename "/home/user/docs/report.pdf" # → report.pdf basename "/home/user/docs/report.pdf" .pdf # → report(自动去掉后缀)
在脚本中:
file="/var/log/syslog" name=$(basename "$file") # → syslog stem=$(basename "$file" .log) # → syslog(若后缀匹配则去除)
⚠️ 注意:始终用双引号包裹变量(如
"$file"),避免空格或特殊字符导致分割错误。
2. 用 Bash 参数扩展(无需外部命令,轻量高效)
file="/opt/app/config.yaml"
name="${file##*/}" # → config.yaml(从最后一个 / 后截取)
stem="${name%.*}" # → config(去掉最后一个点及之后内容)
ext="${name##*.}" # → yaml(取最后一个点之后)-
${var##*/}等价于basename -
${var%.*}只删最后一个点及后缀(适合archive.tar.gz→archive.tar) - 若需删除所有后缀(如
a.b.c→a),可用${var%%.*}
3. 避免用 stat -c "%n" 做 basename 的原因
- 它不解析路径,只是原样回显输入;
- 若你传入的是相对路径(如
../data/file.log),%n仍输出../data/file.log; - 没有内置去路径、去后缀逻辑,必须额外配合
basename或 shell 扩展——那不如直接用后者。
✅ 实用脚本片段示例
#!/bin/bash
for f in /tmp/*.log; do
[[ -e "$f" ]] || continue # 防止无匹配时字面量输出 *.log
name=$(basename "$f")
stem="${name%.*}"
echo "Processing: $stem (from $name)"
# 后续操作,如 gzip "$f" && mv "$f.gz" "/archive/${stem}_$(date +%F).gz"
donestat 在脚本中真正擅长的是获取元数据:大小(%s)、权限(%A)、修改时间(%y)、inode(%i)等。
要取纯名,basename 或 ${var##*/} 更直接、可靠、符合 POSIX。


















