如何在shell脚本中删除文件名的扩展名?

时间:2012-08-28 04:06:05

标签: bash shell sh cut gnu-coreutils

以下代码有什么问题?

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

按原样,我得到文字字符串$filename | cut -f1 -d'.',但如果我删除引号,我什么也得不到。同时输入

"test.exe" | cut -f1 -d'.'
shell中的

为我提供了我想要的输出test。我已经知道$filename已被赋予正确的值。我想要做的是为变量分配没有扩展名的文件名。

15 个答案:

答案 0 :(得分:180)

您还可以使用参数扩展:

$ filename=foo.txt
$ echo "${filename%.*}"
foo

答案 1 :(得分:88)

如果您知道扩展程序,则可以使用basename

{archive}/dSYMs/{yourappname}.app.dSYM/Contents/Resources/DWARF/

答案 2 :(得分:79)

如果要在脚本/命令中执行命令,则应使用command substitution语法$(command)

所以你的行将是

name=$(echo "$filename" | cut -f 1 -d '.')

代码说明:

  1. echo获取变量$filename的值并将其发送到标准输出
  2. 然后我们获取输出并将其传递给cut命令
  3. cut将使用。{作为分隔符(也称为分隔符),用于将字符串剪切成段,-f我们选择要在输出中包含哪个段
  4. 然后$()命令替换将获得输出并返回其值
  5. 返回的值将分配给名为name
  6. 的变量

    请注意,这会将变量的部分提供到第一个句点.

    $ filename=hello.world
    $ echo "$filename" | cut -f 1 -d '.'
    hello
    $ filename=hello.hello.hello
    $ echo "$filename" | cut -f 1 -d '.'
    hello
    $ filename=hello
    $ echo "$filename" | cut -f 1 -d '.'
    hello
    

答案 3 :(得分:15)

如果您的文件名包含一个点(不是扩展名之一),请使用:

echo $filename | rev | cut -f 2- -d '.' | rev

答案 4 :(得分:13)

finally

使用您想要的任何一种。在这里,我假设最后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 (点)后跟文本是扩展名。

答案 5 :(得分:2)

仅使用POSIX的内置功能:

#!/usr/bin/env sh
path=this.path/with.dots/in.path.name/filename.tar.gz

# Get the basedir without external command
# by stripping out shortest trailing match of / followed by anything
dirname=${path%/*}

# Get the basename without external command
# by stripping out longest leading match of anything followed by /
basename=${path##*/}

# Strip uptmost trailing extension only
# by stripping out shortest trailing match of dot followed by anything
oneextless=${basename%.*}; echo "$noext" 

# Strip all extensions
# by stripping out longest trailing match of dot followed by anything
noext=${basename%%.*}; echo "$noext"

# Printout demo
printf %s\\n "$path" "$dirname" "$basename" "$oneextless" "$noext"

打印输出演示:

this.path/with.dots/in.path.name/filename.tar.gz
this.path/with.dots/in.path.name
filename.tar.gz
filename.tar
filename

答案 6 :(得分:1)

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

posts

答案 7 :(得分:1)

我的建议是使用基本名称。
默认情况下,它是ubuntu中的,直观的代码,可以处理大多数情况。 以下是一些处理空格和多点/子扩展名的子案例:

pathfile =“ ../ space fld / space -file.tar.gz”

echo $ {pathfile // +( / |。)}
通常它从一开始就摆脱了扩展。但在我们的..路径中失败

echo “ $(基本名称” $ {pathfile%。*}“)”
space -file.tar#我相信我们确实需要这样做

这里有个重要的注意事项:我在双引号中使用了双引号来处理空格。 由于发短信给$,因此单引号不会通过。 Bash是不寻常的,并且由于扩展而读取“第二个“第一”引号”。

但是,您仍然需要考虑.hidden_​​files

hidden =“〜/ .bashrc” echo“ $(basename” $ {hidden%。}“))”#将产生“〜” !!!
不是预期的“”结果。为此,请使用$ HOME或/ home / user_path /
因为bash再次是“不寻常的”,并且不要展开“〜”(搜索bash BashPitfalls)
hidden2 =“ $ HOME / .bashrc”;回声'$(basename“ $ {pathfile%。
}”)'

答案 8 :(得分:0)

您的代码有两个问题:

  1. 您使用'(tick)代替`(back tick)来围绕生成要存储在变量中的字符串的命令。
  2. 您没有将管道中的变量“$ filename”“回显”到“cut”命令中。
  3. 我将你的代码更改为“name =`echo $ filename | cut -f 1 -d'。' `“,如下所示(再次注意名称变量定义的后面的滴答声):

    $> filename=foo.txt
    $> echo $filename
    foo.txt
    $> name=`echo $filename | cut -f1 -d'.'`
    $> echo $name
    foo
    $> 
    

答案 9 :(得分:0)

#!/bin/bash
filename=program.c
name=$(basename "$filename" .c)
echo "$name"

输出:

program

答案 10 :(得分:0)

O(1)

输出:

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

请注意,仅删除最后一个扩展名。

答案 11 :(得分:0)

如果我错了,请纠正我。 当我尝试通过CLI(命令行界面)对文件进行任何更新时,请执行以下操作:

1-例如,我有一个文件test.txt,现在我可以很好地创建它:

touch test.txt

2-现在,我可以使用以下命令备份文件了:

cp test.txt{,.bak}

3-免于查看目录

ll

我们现在找到了两个文件test.txt和test.txt.bak

4-现在,如果我们在内部出错,我们可以删除原始文件test.txt

rm test.txt

5-下面的命令很好地从备份中还原了原始文件

cp test.txt.bak test.txt

6-如果现在列出目录文件,我们可以找到test.txt和 test.txt.bak:

ll

7-现在删除不需要的test.txt.bak,如下所示

rm test.txt.bak

8-您在安全方面进行了更新。

答案 12 :(得分:0)

以前提供的答案在包含点的路径方面存在问题。一些例子:

/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

答案 13 :(得分:0)

这个涵盖了所有的可能性! (路径中有没有点;有扩展名或没有扩展名):

tmp1=${filename##*/};tmp2=${tmp1:1};filename_noextension=$(echo -n ${tmp1:0:1};echo ${tmp2%.*});echo $filename_noextension

注意事项:

  • 它为您提供没有任何扩展名的文件名。所以 $filename_noextension 变量中没有路径。
  • 您最终会得到两个不需要的变量 $tmp1$tmp2。确保您没有在脚本中使用它们。

测试示例:

filename=.bashrc; echo "filename: $filename"; tmp1=${filename##*/};tmp2=${tmp1:1};filename_noextension=$(echo -n ${tmp1:0:1};echo ${tmp2%.*}); echo "filename without extension: $filename_noextension"

filename=.bashrc.txt; echo "filename: $filename"; tmp1=${filename##*/};tmp2=${tmp1:1};filename_noextension=$(echo -n ${tmp1:0:1};echo ${tmp2%.*}); echo "filename without extension: $filename_noextension"

filename=.bashrc.txt.tar; echo "filename: $filename"; tmp1=${filename##*/};tmp2=${tmp1:1};filename_noextension=$(echo -n ${tmp1:0:1};echo ${tmp2%.*}); echo "filename without extension: $filename_noextension"

filename=~/.bashrc; echo "filename: $filename"; tmp1=${filename##*/};tmp2=${tmp1:1};filename_noextension=$(echo -n ${tmp1:0:1};echo ${tmp2%.*}); echo "filename without extension: $filename_noextension"

filename=~/.bashrc.txt.tar; echo "filename: $filename"; tmp1=${filename##*/};tmp2=${tmp1:1};filename_noextension=$(echo -n ${tmp1:0:1};echo ${tmp2%.*}); echo "filename without extension: $filename_noextension"

filename=bashrc; echo "filename: $filename"; tmp1=${filename##*/};tmp2=${tmp1:1};filename_noextension=$(echo -n ${tmp1:0:1};echo ${tmp2%.*}); echo "filename without extension: $filename_noextension"

filename=bashrc.txt; echo "filename: $filename"; tmp1=${filename##*/};tmp2=${tmp1:1};filename_noextension=$(echo -n ${tmp1:0:1};echo ${tmp2%.*}); echo "filename without extension: $filename_noextension"

filename=bashrc.txt.tar; echo "filename: $filename"; tmp1=${filename##*/};tmp2=${tmp1:1};filename_noextension=$(echo -n ${tmp1:0:1};echo ${tmp2%.*}); echo "filename without extension: $filename_noextension"

filename=~/bashrc; echo "filename: $filename"; tmp1=${filename##*/};tmp2=${tmp1:1};filename_noextension=$(echo -n ${tmp1:0:1};echo ${tmp2%.*}); echo "filename without extension: $filename_noextension"

filename=~/bashrc.txt.tar; echo "filename: $filename"; tmp1=${filename##*/};tmp2=${tmp1:1};filename_noextension=$(echo -n ${tmp1:0:1};echo ${tmp2%.*}); echo "filename without extension: $filename_noextension"

答案 14 :(得分:-1)

enter image description here

假设您的文件具有 .new 扩展名

ls -1 | awk '{ 打印 "mv "$1" basename "$1" .new"}' |嘘

由于发帖后没有特别引述,请看图。