我想分别获取文件名(不带扩展名)和扩展名。

到目前为止,我找到的最佳解决方案是:

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解释器。

有更好的主意吗?


当前回答

~% FILE="example.tar.gz"

~% echo "${FILE%%.*}"
example

~% echo "${FILE%.*}"
example.tar

~% echo "${FILE#*.}"
tar.gz

~% echo "${FILE##*.}"
gz

有关详细信息,请参阅Bash手册中的shell参数扩展。

其他回答

您可以使用

sed 's/^/./' | rev | cut -d. -f2- | rev | cut -c2-

获取文件名和

sed 's/^/./' | rev | cut -d. -f1  | rev

以获得扩展。

测试用例:

echo "filename.gz"     | sed 's/^/./' | rev | cut -d. -f2- | rev | cut -c2-
echo "filename.gz"     | sed 's/^/./' | rev | cut -d. -f1  | rev
echo "filename"        | sed 's/^/./' | rev | cut -d. -f2- | rev | cut -c2-
echo "filename"        | sed 's/^/./' | rev | cut -d. -f1  | rev
echo "filename.tar.gz" | sed 's/^/./' | rev | cut -d. -f2- | rev | cut -c2-
echo "filename.tar.gz" | sed 's/^/./' | rev | cut -d. -f1  | rev

从Petersh答案构建,如果只需要文件名,路径和延伸都可以在单行中剥离,

filename=$(basename ${fullname%.*})

您还可以使用for循环和tr从路径中提取文件名。。。

for x in `echo $path | tr "/" " "`; do filename=$x; done

tr将路径中的所有“/”分隔符替换为空格,从而生成字符串列表,for循环扫描它们,最后一个在文件名变量中。

Mellen在一篇博客文章中写道:

使用Bash,还有${file%.*}获取不带扩展名的文件名,${file##*.}单独获取扩展名。即,

file="thisfile.txt"
echo "filename: ${file%.*}"
echo "extension: ${file##*.}"

输出:

filename: thisfile
extension: txt

首先,获取不带路径的文件名:

filename=$(basename -- "$fullfile")
extension="${filename##*.}"
filename="${filename%.*}"

或者,您可以关注路径的最后一个“/”,而不是“.”即使您有不可预知的文件扩展名,也可以使用:

filename="${fullfile##*/}"

您可能需要检查文档:

在网页“3.5.3外壳参数扩展”部分在bash手册页的“参数扩展”部分