下面的代码有什么问题?
name='$filename | cut -f1 -d'.''
就像这样,我得到的字面值字符串$filename | cut -f1 -d'。',但如果我删除引号,我什么也得不到。与此同时,打字
"test.exe" | cut -f1 -d'.'
在shell中给出我想要的输出,test。我已经知道$filename已经被分配了正确的值。我要做的是给一个变量分配没有扩展名的文件名。
下面的代码有什么问题?
name='$filename | cut -f1 -d'.''
就像这样,我得到的字面值字符串$filename | cut -f1 -d'。',但如果我删除引号,我什么也得不到。与此同时,打字
"test.exe" | cut -f1 -d'.'
在shell中给出我想要的输出,test。我已经知道$filename已经被分配了正确的值。我要做的是给一个变量分配没有扩展名的文件名。
当前回答
#!/bin/bash
file=/tmp/foo.bar.gz
echo $file ${file%.*}
输出:
/tmp/foo.bar.gz /tmp/foo.bar
注意,只有最后一个扩展被删除。
其他回答
如果知道扩展名,可以使用basename
$ basename /home/jsmith/base.wiki .wiki
base
你的代码有两个问题:
您使用' (tick)而不是'(反tick)来包围生成想要存储在变量中的字符串的命令。 您没有将变量“$filename”“echo”到管道中的“cut”命令中。
我会把你的代码改为"name= ' echo $filename | cut -f 1 -d '。' ' ",如下所示(再次注意,后面的勾号围绕着name变量定义):
$> filename=foo.txt
$> echo $filename
foo.txt
$> name=`echo $filename | cut -f1 -d'.'`
$> echo $name
foo
$>
在Zsh:
fullname=bridge.zip
echo ${fullname:r}
它简单,干净,可以被链接以删除多个扩展:
fullname=bridge.tar.gz
echo ${fullname:r:r}
它可以与其他类似的修饰语结合使用。
你也可以使用参数展开:
$ filename=foo.txt
$ echo "${filename%.*}"
foo
只是要注意,如果没有文件扩展名,它将进一步向后寻找点,例如。
如果文件名只是以点开始(例如。bashrc),它将删除整个文件名。 如果只在路径中有一个点(例如path。到/myfile或。/myfile),那么它将在路径内部进行修剪。
之前提供的答案在包含点的路径上有问题。一些例子:
/xyz.dir/file.ext
./file.ext
/a.b.c/x.ddd.txt
我更喜欢使用|sed -e 's/\.[^./]*$//'。例如:
$ echo "/xyz.dir/file.ext" | sed -e 's/\.[^./]*$//'
/xyz.dir/file
$ echo "./file.ext" | sed -e 's/\.[^./]*$//'
./file
$ echo "/a.b.c/x.ddd.txt" | sed -e 's/\.[^./]*$//'
/a.b.c/x.ddd
注意:如果你想删除多个扩展(就像上一个例子一样),使用|sed -e 's/\.[^/]*$//':
$ echo "/a.b.c/x.ddd.txt" | sed -e 's/\.[^/]*$//'
/a.b.c/x
但是,该方法在没有扩展名的“点文件”中会失败:
$ echo "/a.b.c/.profile" | sed -e 's/\.[^./]*$//'
/a.b.c/
为了涵盖这些情况,你可以使用:
$ echo "/a.b.c/.profile" | sed -re 's/(^.*[^/])\.[^./]*$/\1/'
/a.b.c/.profile