| 知乎专栏 |
basename 命令用于提取文件路径中的文件名部分,即去掉目录路径和可选的后缀。
basename 名称 [后缀] basename 选项... 名称...
常用选项:
-s, --suffix=SUFFIX - 删除指定的后缀
-a, --multiple - 支持多个参数
-z, --zero - 输出以 NUL 结尾而非换行符
--help - 显示帮助信息
--version - 显示版本信息
提取文件名:
$ basename /usr/bin/find find $ basename /etc/nginx/nginx.conf nginx.conf $ basename /var/log/syslog syslog $ basename ./script.sh script.sh
删除指定后缀:
$ basename /etc/nginx/nginx.conf .conf nginx $ basename /path/to/file.tar.gz .gz file.tar $ basename document.pdf .pdf document
使用 -s 选项删除后缀:
$ basename -s .txt readme.txt readme $ basename -s .sh script.sh script
处理多个文件(使用 -a):
$ basename -a /path/to/file1.txt /path/to/file2.txt file1.txt file2.txt $ basename -s .txt -a /path/to/file1.txt /path/to/file2.txt file1 file2
使用 basename 命令删除扩展名:
$ basename test.txt .txt test $ basename archive.tar.gz .tar.gz archive
使用 Shell 参数展开删除扩展名:
file=test.txt
b=${file%.*}
echo $b
批量重命名文件(删除扩展名或更改扩展名):
$ for file in *.JPG;do mv $file ${file%.*}.jpg;done
# 或者使用 rename 命令
$ rename 's/\.JPG$/.jpg/' *.JPG
使用 Shell 参数展开提取文件扩展名:
file=test.txt
b=${file##*.}
echo $b
更多扩展名处理示例:
# 单扩展名
file=document.pdf
echo "${file##*.}" # 输出: pdf
# 多扩展名(取最后一个)
file=archive.tar.gz
echo "${file##*.}" # 输出: gz
# 取所有扩展名
file=archive.tar.gz
echo "${file#*.}" # 输出: tar.gz
# 没有扩展名
file=Makefile
echo "${file##*.}" # 输出: Makefile(与文件名相同)
# 隐藏文件
file=.gitignore
echo "${file##*.}" # 输出: gitignore
在脚本中获取文件名(不含路径):
#!/bin/bash
for filepath in /var/log/*.log; do
filename=$(basename "$filepath")
echo "处理文件: $filename"
done
备份文件时保留原始文件名:
src="/etc/nginx/nginx.conf"
filename=$(basename "$src")
cp "$src" "/backup/${filename}.bak"
批量转换文件格式:
# 将所有 .txt 文件转换为 .md
for file in *.txt; do
name=$(basename "$file" .txt)
mv "$file" "${name}.md"
done
创建日志文件:
script_name=$(basename "$0" .sh)
log_file="/var/log/${script_name}.log"
echo "$(date): 脚本开始" >> "$log_file"
dirname 和 basename 可以完整分解文件路径:
filepath="/usr/local/bin/script.sh"
dir=$(dirname "$filepath") # /usr/local/bin
file=$(basename "$filepath") # script.sh
echo "目录: $dir"
echo "文件: $file"
# 重新组合
echo "${dir}/${file}" # /usr/local/bin/script.sh
移动文件到另一个目录但保持文件名:
src="/tmp/data.csv"
dest_dir="/var/data"
filename=$(basename "$src")
mv "$src" "${dest_dir}/${filename}"
在 Bash 中可以使用参数展开实现 basename 的功能:
filepath="/usr/local/bin/script.sh"
# basename 等价于
echo "${filepath##*/}" # 输出: script.sh
# basename 删除后缀等价于
echo "${filepath##*/}" | sed 's/\.[^.]*$//' # 输出: script
# 或使用两层展开
base="${filepath##*/}"
echo "${base%.*}" # 输出: script
# 特殊情况
filepath="script.sh"
echo "${filepath##*/}" # 输出: script.sh
basename "$filepath" # 输出: script.sh
参数展开比调用 basename 命令更快(无需创建子进程),适合在循环中使用。
处理包含空格的文件名时必须加引号:
# 错误 - 空格会导致问题 basename /path/with spaces/file.txt # 输出: file.txt(但可能在其他命令中出错) # 正确 - 使用引号 basename "/path/with spaces/file.txt" # 输出: file.txt
后缀匹配是精确的字符串匹配:
# .gz 只匹配 .gz,不匹配 .tar.gz
$ basename archive.tar.gz .gz
archive.tar
$ basename archive.tar.gz .tar.gz
archive
# 如果要删除多层后缀,需要多次处理或使用 ${file%.*}
file=archive.tar.gz
echo "${file%.*}" # archive.tar
echo "${file%%.*}" # archive(删除所有后缀)
路径末尾的斜杠会被忽略:
$ basename /usr/bin/ bin $ basename /usr/bin bin
提取文件名(不含扩展名)的多种方法:
file="/path/to/document.pdf"
# 方法 1: basename + sed
basename "$file" | sed 's/\.[^.]*$//'
# 方法 2: 参数展开(推荐)
base=$(basename "$file")
echo "${base%.*}"
# 方法 3: 纯参数展开
base="${file##*/}"
echo "${base%.*}"
批量重命名文件:
# 将所有 .jpeg 重命名为 .jpg
for file in *.jpeg; do
newname=$(basename "$file" .jpeg).jpg
mv "$file" "$newname"
done
# 为所有文件添加时间戳前缀
timestamp=$(date +%Y%m%d)
for file in *.txt; do
mv "$file" "${timestamp}_${file}"
done