问题
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:
echo
get the value of the variable$filename
and send it to standard output- We then grab the output and pipe it to the
cut
command - 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 - Then the
$()
command substitution will get the output and return its value - 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:
- You used a ' (tick) instead of a ` (back tick) to surround the commands that generate the string you want to store in the variable.
- 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