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

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

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

有更好的主意吗?


当前回答

您可以使用POSIX参数扩展的魔力:

bash-3.2$ FILENAME=somefile.tar.gz
bash-3.2$ echo "${FILENAME%%.*}"
somefile
bash-3.2$ echo "${FILENAME%.*}"
somefile.tar

如果您的文件名是这样的格式,则需要注意/somefile.tar.gz然后echo${FILENAME%%.*}会贪婪地删除最长的匹配项。你会得到空字符串。

(您可以使用临时变量解决此问题:

FULL_FILENAME=$FILENAME
FILENAME=${FULL_FILENAME##*/}
echo ${FILENAME%%.*}

)


本网站提供了更多信息。

${variable%pattern}
  Trim the shortest match from the end
${variable##pattern}
  Trim the longest match from the beginning
${variable%%pattern}
  Trim the longest match from the end
${variable#pattern}
  Trim the shortest match from the beginning

其他回答

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

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

您可以使用basename。

例子:

$ basename foo-bar.tar.gz .tar.gz
foo-bar

您确实需要为basename提供要删除的扩展名,但是如果您总是使用-z执行tar,那么您知道扩展名将是.tar.gz。

这应该可以满足您的需要:

tar -zxvf $1
cd $(basename $1 .tar.gz)

一个简单的答案:

要扩展POSIX变量答案,请注意您可以执行更多有趣的模式。因此,对于此处详述的案例,您可以简单地执行以下操作:

tar -zxvf $1
cd ${1%.tar.*}

这将切断.tar.<something>的最后一次出现。

更一般地,如果要删除最后一次出现的<一些><其他>然后

${1.*.*}

应该工作正常。

上述答案的链接似乎已失效。这是一个很好的解释,可以直接在Bash中使用TLDP进行一系列字符串操作。

$ F = "text file.test.txt"  
$ echo ${F/*./}  
txt  

这可以满足文件名中的多个点和空格,但是如果没有扩展名,则返回文件名本身。但易于检查;只需测试文件名和扩展名是否相同。

自然,此方法不适用于.tar.gz文件。然而,这可以分两步处理。如果扩展名是gz,则再次检查是否也有tar扩展名。

从上面的答案来看,模仿Python的最短一行代码

file, ext = os.path.splitext(path)

假设您的文件确实有扩展名

EXT="${PATH##*.}"; FILE=$(basename "$PATH" .$EXT)