下面的代码有什么问题?

name='$filename | cut -f1 -d'.''

就像这样,我得到的字面值字符串$filename | cut -f1 -d'。',但如果我删除引号,我什么也得不到。与此同时,打字

"test.exe" | cut -f1 -d'.'

在shell中给出我想要的输出,test。我已经知道$filename已经被分配了正确的值。我要做的是给一个变量分配没有扩展名的文件名。


当前回答

我的建议是使用basename。 它在Ubuntu中是默认的,直观的代码简单,可以处理大多数情况。

下面是一些处理空格和多点/子扩展的子案例:

pathfile="../space fld/space -file.tar.gz"
echo ${pathfile//+(*\/|.*)}

它通常从一开始就去掉扩展,但在我们的…路径

echo **"$(basename "${pathfile%.*}")"**  
space -file.tar     # I believe we needed exatly that

这里有一个重要的提示:

我在双引号中使用双引号来处理空格。 单报价将不通过由于短信$。 Bash是不寻常的,由于扩展,读取“第二个”和“第一个”引号。

但是,您仍然需要考虑.hidden_files

hidden="~/.bashrc"
echo "$(basename "${hidden%.*}")"  # will produce "~" !!!  

不是预期的“”结果。使用$HOME或/home/user_path/ 因为bash是“不寻常的”,不要展开“~”(搜索bash bash)

hidden2="$HOME/.bashrc" ;  echo '$(basename "${pathfile%.*}")'

其他回答

#!/bin/bash
file=/tmp/foo.bar.gz
echo $file ${file%.*}

输出:

/tmp/foo.bar.gz /tmp/foo.bar

注意,只有最后一个扩展被删除。

file1=/tmp/main.one.two.sh
t=$(basename "$file1")                        # output is main.one.two.sh
name=$(echo "$file1" | sed -e 's/\.[^.]*$//') # output is /tmp/main.one.two
name=$(echo "$t" | sed -e 's/\.[^.]*$//')     # output is main.one.two

你想用哪个就用哪个。这里我假设是最后一个。(点)后面跟着文本是扩展。

我的建议是使用basename。 它在Ubuntu中是默认的,直观的代码简单,可以处理大多数情况。

下面是一些处理空格和多点/子扩展的子案例:

pathfile="../space fld/space -file.tar.gz"
echo ${pathfile//+(*\/|.*)}

它通常从一开始就去掉扩展,但在我们的…路径

echo **"$(basename "${pathfile%.*}")"**  
space -file.tar     # I believe we needed exatly that

这里有一个重要的提示:

我在双引号中使用双引号来处理空格。 单报价将不通过由于短信$。 Bash是不寻常的,由于扩展,读取“第二个”和“第一个”引号。

但是,您仍然需要考虑.hidden_files

hidden="~/.bashrc"
echo "$(basename "${hidden%.*}")"  # will produce "~" !!!  

不是预期的“”结果。使用$HOME或/home/user_path/ 因为bash是“不寻常的”,不要展开“~”(搜索bash bash)

hidden2="$HOME/.bashrc" ;  echo '$(basename "${pathfile%.*}")'
#!/bin/bash
filename=program.c
name=$(basename "$filename" .c)
echo "$name"

输出:

program

正如Hawker65在chepner answer的评论中指出的那样,投票最多的解决方案既不关心多个扩展名(如filename.tar.gz),也不关心路径其余部分的点(如this.path/with.dots/in.path.name)。 一个可能的解决方案是:

a=this.path/with.dots/in.path.name/filename.tar.gz
echo $(dirname $a)/$(basename $a | cut -d. -f1)