[英]How can I remove the extension of a filename in a shell script?
以下代碼有什么問題?
name='$filename | cut -f1 -d'.''
照原樣,我得到文字字符串$filename | cut -f1 -d'.'
$filename | cut -f1 -d'.'
,但如果我刪除引號,我將一無所獲。 同時,鍵入
"test.exe" | cut -f1 -d'.'
在 shell 中給了我我想要的輸出, test
。 我已經知道$filename
已分配正確的值。 我想要做的是將沒有擴展名的文件名分配給變量。
您還可以使用參數擴展:
$ filename=foo.txt
$ echo "${filename%.*}"
foo
請注意,如果沒有文件擴展名,它將進一步查找點,例如
.bashrc
),它將刪除整個文件名。path.to/myfile
或./myfile
),那么它將在路徑內修剪。當您想在腳本/命令中執行命令時,您應該使用命令替換語法$(command)
。
所以你的線路將是
name=$(echo "$filename" | cut -f 1 -d '.')
代碼說明:
echo
獲取變量$filename
的值並將其發送到標准輸出cut
命令cut
將使用 . 作為分隔符(也稱為分隔符)用於將字符串切割成段,並通過-f
我們選擇我們想要在輸出中包含的段$()
命令替換將獲得輸出並返回其值name
的變量請注意,這給出了直到第一個期間的變量部分.
:
$ 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
如果您知道擴展名,則可以使用basename
$ basename /home/jsmith/base.wiki .wiki
base
如果您的文件名包含一個點(擴展名除外),請使用以下命令:
echo $filename | rev | cut -f 2- -d '.' | rev
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
使用任何你想要的。 在這里,我假設最后.
(點)后跟文本是擴展名。
僅使用 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
#!/bin/bash
file=/tmp/foo.bar.gz
echo $file ${file%.*}
輸出:
/tmp/foo.bar.gz /tmp/foo.bar
請注意,僅刪除了最后一個擴展名。
我的建議是使用basename
。
它在 Ubuntu 中是默認的,視覺上簡單的代碼並處理大多數情況。
以下是處理空格和多點/子擴展的一些子案例:
pathfile="../space fld/space -file.tar.gz"
echo ${pathfile//+(*\/|.*)}
它通常從 first 擺脫擴展.
,但在我們的..
路徑中失敗
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 BashPitfalls)
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)
先前提供的答案在包含點的路徑方面存在問題。 一些例子:
/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
您的代碼有兩個問題:
我會將您的代碼更改為“name=`echo $filename | cut -f 1 -d '。” `",如下所示(再次注意名稱變量定義周圍的反引號):
$> filename=foo.txt
$> echo $filename
foo.txt
$> name=`echo $filename | cut -f1 -d'.'`
$> echo $name
foo
$>
如果我錯了請指正。 當我嘗試通過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-您在安全方面進行了更新。
這個涵蓋了所有的可能性! (路徑中是否有點;有擴展名或沒有擴展名):
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"
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.