How can I remove the extension of a filename in a shell script?

一曲冷凌霜 提交于 2019-12-17 03:23:58

问题


What's wrong with the following code?

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

As is, I get the literal string $filename | cut -f1 -d'.', but if I remove the quotes I don't get anything. Meanwhile typing

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

in a shell gives me the output I want, test. I already know $filename has been assigned the right value. What I want to do is assign to a variable the filename without the extension.


回答1:


You should be using the command substitution syntax $(command) when you want to execute a command in script/command.

So your line would be

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

Code explanation:

  1. echo get the value of the variable $filename and send it to standard output
  2. We then grab the output and pipe it to the cut command
  3. The cut will use the . as delimiter (also known as separator) for cutting the string into segments and by -f we select which segment we want to have in output
  4. Then the $() command substitution will get the output and return its value
  5. The returned value will be assigned to the variable named name

Note that this gives the portion of the variable up to the first period .:

$ 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



回答2:


You can also use parameter expansion:

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



回答3:


If you know the extension, you can use basename

$ basename /home/jsmith/base.wiki .wiki
base



回答4:


If your filename contains a dot (other than the one of the extension) then use this:

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



回答5:


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

use whichever you want. Here I assume that last . (dot) followed by text is extension.




回答6:


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

outputs:

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

Note that only the last extension is removed.




回答7:


As pointed out by Hawker65 in the comment of chepner answer, the most voted solution does neither take care of multiple extensions (such as filename.tar.gz), nor of dots in the rest of the path (such as this.path/with.dots/in.path.name). A possible solution is:

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



回答8:


My recommendation is to use basename.
It is by default in Ubuntu, visually simple code and deal with majority of cases.

Here are some sub-cases to deal with spaces and multi-dot/sub-extension:

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

It usually get rid of extension from first ., but fail in our .. path

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

Here is an important note:

I used double quotes inside double quotes to deal with spaces. Single quote will not pass due to texting the $. Bash is unusual and reads "second "first" quotes" due to expansion.

However, you still need to think of .hidden_files

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

not the expected "" outcome. To make it happen use $HOME or /home/user_path/
because again bash is "unusual" and don't expand "~" (search for bash BashPitfalls)

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



回答9:


Two problems with your code:

  1. You used a ' (tick) instead of a ` (back tick) to surround the commands that generate the string you want to store in the variable.
  2. You didn't "echo" the variable "$filename" to the pipe into the "cut" command.

I'd change your code to "name=`echo $filename | cut -f 1 -d '.' `", as shown below (again, notice the back ticks surrounding the name variable definition):

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



回答10:


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

outputs:

program



回答11:


Correct me if I'm wrong please. When I try to do any updates to a file from CLI (Command Line Interface).I do as below:

1- For example I have a file test.txt I well create now:

touch test.txt

2- Now I well backup the file using the below command:

cp test.txt{,.bak}

3- Lest's see the directory

ll

We well find two files now test.txt and test.txt.bak

4- Now we well delete the original file test.txt if we made mistakes inside

rm test.txt

5- The below command well restore the original file from backup

cp test.txt.bak test.txt

6- If we list the directory files now we well find test.txt and test.txt.bak:

ll

7- Now delete the test.txt.bak fi you do not need any more as show below

rm test.txt.bak

8- You made the updates while you was in the safe side.



来源:https://stackoverflow.com/questions/12152626/how-can-i-remove-the-extension-of-a-filename-in-a-shell-script

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!