以下代码有什么问题?
name='$filename | cut -f1 -d'.''
照原样,我得到了文字 string $filename | cut -f1 -d'.'
,但是如果我删除引号,我什么也得不到。同时,键入
"test.exe" | cut -f1 -d'.'
在 shell 中给了我想要的输出,test
. 我已经知道$filename
已经分配了正确的值。我想要做的是将不带扩展名的文件名分配给变量。
以下代码有什么问题?
name='$filename | cut -f1 -d'.''
照原样,我得到了文字 string $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 "$oneextless"
# 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//+(*\/|.*)}
它通常从一开始就摆脱扩展,但在我们的道路.
上失败了..
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%.*}")'
以前提供的答案在包含点的路径方面存在问题。一些例子:
/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
#!/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)
这个涵盖了所有的可能性!(路径中的点与否;有扩展名或无扩展名):
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"
您的代码有两个问题:
我会将您的代码更改为“name=`echo $filename | cut -f 1 -d '。” `",如下所示(再次注意名称变量定义周围的反引号):
$> 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}
并且可以与其他类似的修饰符组合使用。