我想分别获取文件名(不带扩展名)和扩展名。
到目前为止,我找到的最佳解决方案是:
NAME=`echo "$FILE" | cut -d'.' -f1`
EXTENSION=`echo "$FILE" | cut -d'.' -f2`
这是错误的,因为如果文件名包含多个,它就不起作用。字符。假设我有a.b.js,它会考虑a和b.js而不是a.b和js。
它可以在Python中用
file, ext = os.path.splitext(path)
但如果可能的话,我不希望仅仅为此启动Python解释器。
有更好的主意吗?
使用示例文件/Users/Jonathan/Scripts/bash/MyScript.sh,以下代码:
MY_EXT=".${0##*.}"
ME=$(/usr/bin/basename "${0}" "${MY_EXT}")
将导致${ME}为MyScript,${MY_EXT}为.sh:
脚本:
#!/bin/bash
set -e
MY_EXT=".${0##*.}"
ME=$(/usr/bin/basename "${0}" "${MY_EXT}")
echo "${ME} - ${MY_EXT}"
一些测试:
$ ./MyScript.sh
MyScript - .sh
$ bash MyScript.sh
MyScript - .sh
$ /Users/Jonathan/Scripts/bash/MyScript.sh
MyScript - .sh
$ bash /Users/Jonathan/Scripts/bash/MyScript.sh
MyScript - .sh
对于这个简单的任务,无需使用awk或sed,甚至perl。有一个纯Bash,os.path.splitext()兼容的解决方案,它只使用参数扩展。
参考实施
os.path.splitext(路径)的文档:
将路径名路径拆分为一对(root、ext),使root+ext==路径,ext为空或以句点开头,最多包含一个句点。基名上的前导句点被忽略;splitext('.cshrc')返回('.cshrc','')。
Python代码:
root, ext = os.path.splitext(path)
Bash实现
表彰领先时期
root="${path%.*}"
ext="${path#"$root"}"
忽略前导期
root="${path#.}";root="${path%"$root"}${root%.*}"
ext="${path#"$root"}"
测验
下面是忽略前导周期实现的测试用例,它应该与每个输入上的Python引用实现相匹配。
|---------------|-----------|-------|
|path |root |ext |
|---------------|-----------|-------|
|' .txt' |' ' |'.txt' |
|' .txt.txt' |' .txt' |'.txt' |
|' txt' |' txt' |'' |
|'*.txt.txt' |'*.txt' |'.txt' |
|'.cshrc' |'.cshrc' |'' |
|'.txt' |'.txt' |'' |
|'?.txt.txt' |'?.txt' |'.txt' |
|'\n.txt.txt' |'\n.txt' |'.txt' |
|'\t.txt.txt' |'\t.txt' |'.txt' |
|'a b.txt.txt' |'a b.txt' |'.txt' |
|'a*b.txt.txt' |'a*b.txt' |'.txt' |
|'a?b.txt.txt' |'a?b.txt' |'.txt' |
|'a\nb.txt.txt' |'a\nb.txt' |'.txt' |
|'a\tb.txt.txt' |'a\tb.txt' |'.txt' |
|'txt' |'txt' |'' |
|'txt.pdf' |'txt' |'.pdf' |
|'txt.tar.gz' |'txt.tar' |'.gz' |
|'txt.txt' |'txt' |'.txt' |
|---------------|-----------|-------|
测试结果
所有测试均通过。