linux不带路径,关于Linux:在bash中提取不带路径和扩展名的文件basename

本问题已经有最佳答案,请猛点这里访问。

给定的文件名如下:

/the/path/foo.txt

bar.txt

我希望得到:

foo

bar

为什么这样不行?

#!/bin/bash

fullfile=$1

fname=$(basename $fullfile)

fbname=${fname%.*}

echo $fbname

正确的方法是什么?

只要EDOCX1的值(0)实际上是您所认为的值,那么在大多数情况下,该代码都可以工作。但是,由于引用不当,会导致分词和扩展文件名。

您不必调用外部basename命令。相反,您可以使用以下命令:

$ s=/the/path/foo.txt

$ echo ${s##*/}

foo.txt

$ s=${s##*/}

$ echo ${s%.txt}

foo

$ echo ${s%.*}

foo

请注意,此解决方案应适用于最近(2004年后)所有符合POSIX的shell(如bash、dash、ksh等)。

来源:shell命令语言2.6.2参数扩展

关于bash字符串操作的更多信息:http://tldp.org/ldp/lg/issue18/bash.html

完美的答案…这里解释了bash字符串操作(如${s##*/})linuxgazette.net/18/bash.html

@你找到链接的更新参考了吗?它死了。

@Droogans是在挖掘之后发现的:)t ldp.org/ldp/lg/issue18/bash.html没有意识到我对这个评论有27个赞成票:)

非常方便,用于文件扩展和选择。示例:options=~/path/user.*,然后是select result in ${options[@]##*/};。

有没有办法将##*/与%.*结合起来(通过嵌套或管道或其他方式)直接到达foo?

顺便说一句,TLDP的文档没有很好地维护;wiki.bash-hacker.org/syntax/pe和mywiki.wooledge.org/bashfaq/100可能是更好的参考。

@bongbang,不;bash不允许嵌套pes。(zsh有,但在这方面几乎是孤独的)。

在输出如前所述的Ubuntu bash脚本中不工作

@Bongbang-你可以把所有东西都放在一行中,在这篇文章中稍加修改,请参见stackoverflow.com/a/36341390/2707864。

Linux Gazette链接现在已断开:lg 18现在可通过tldp.org/ldp/lg/issue18/bash.html获得。

仅供参考,也在zsh上工作。

文件也可通过man -P"less -p 'Parameter Expansion'" bash获得。

@Chim上述链接已断开。这里是存档版本web beta.archive.org/web/20111026140412/http://hellip;

你怎么在fish里做这个?

如果我的路径类似于user/my_folder/[this_is_my_file]*,会发生什么?当我遵循这些步骤时,我得到的是[this_is_my_file]*。

basename命令有两种不同的调用;一种是只指定路径,在这种情况下,它会给出最后一个组件,而在另一种情况下,它还会给出一个将要删除的后缀。因此,您可以使用第二次调用basename来简化示例代码。此外,请注意正确引用以下内容:

fbname=$(basename"$1" .txt)

echo"$fbname"

有没有办法让它去掉任何后缀?

@不幸的是,basename不支持通配符。提供第二个参数只会从结尾处删除该确切的文本字符串。

在basename为8.4的机器上,它的工作方式与此答案中指定的一样,但对于我(从GNU coreutils获得basename为8.22)来说,它的工作方式是basename -s。

@w4etwetewtwet-您可以让basename删除任何扩展名,请参阅stackoverflow.com/a/36341390/2707864

basename和cut的组合效果很好,即使是像.tar.gz这样的双端:

fbname=$(basename"$fullfile" | cut -d. -f1)

如果这个解决方案比bash参数扩展需要更少的算术能力,那就很有趣了。

这是我的首选方式——使用$(..)的微小变化——所以这变成了:fbname=$(basename"$fullfile" | cut -d. -f1)。

这是一个很好的解决方案,因为它将截取所有(点)扩展。

如果文件名中的其他地方有点,则会错误地截断它。这可能会更好:fbname=$(basename"$fullfile" | sed -r 's|^(.*?)\.\w+$|\1|')。更多选择:'s|^(.*?)\..+$|\1|'、's|^(.*?)\.[^\.]+$|\1|'。

纯bash,无basename,无变戏法。设置字符串和echo:

s=/the/path/foo.txt

echo ${s//+(*\/|.*)}

输出:

foo

注:bashextglob选项必须为"on"(在Ubuntu上默认为"on"),否则,请执行以下操作:

shopt -s extglob

走过${s//+(*\/|.*)}:

${s--从$s开始。

//替代了模式的每个实例。

+(匹配括号中的一个或多个模式列表。

*\/匹配/之前的任何内容。(第一种模式)

|或。(模式分隔符。)

.*匹配.之后的任何内容。(第二种模式)

)端模式列表。

}结束参数扩展——由于没有/(在字符串替换之前),匹配的模式将被删除。

相关man bash背景:

模式替换:

${parameter/pattern/string}

Pattern substitution.  The pattern is expanded to produce a pat‐

tern just as in pathname expansion.  Parameter is  expanded  and

the  longest match of pattern against its value is replaced with

string.  If pattern begins with /, all matches  of  pattern  are

replaced   with  string.   Normally  only  the  first  match  is

replaced.  If pattern begins with #, it must match at the begin‐

ning of the expanded value of parameter.  If pattern begins with

%, it must match at the end of the expanded value of  parameter.

If string is null, matches of pattern are deleted and the / fol‐

lowing pattern may be omitted.  If parameter is @ or *, the sub‐

stitution  operation  is applied to each positional parameter in

turn, and the expansion is the resultant list.  If parameter  is

an  array  variable  subscripted  with  @ or *, the substitution

operation is applied to each member of the array  in  turn,  and

the expansion is the resultant list.

扩展模式匹配:

If the extglob shell option is enabled using the shopt builtin, several

extended  pattern  matching operators are recognized.  In the following

description, a pattern-list is a list of one or more patterns separated

by a |.  Composite patterns may be formed using one or more of the fol‐

lowing sub-patterns:

?(pattern-list)

Matches zero or one occurrence of the given patterns

*(pattern-list)

Matches zero or more occurrences of the given patterns

+(pattern-list)

Matches one or more occurrences of the given patterns

@(pattern-list)

Matches one of the given patterns

!(pattern-list)

Matches anything except one of the given patterns

以下是一句话:

$(basename ${s%.*})

$(basename ${s} .${s##*.})

我需要这个,就像邦邦和W4etwetwet要求的那样。

以下是获取文件名或扩展名的另一种(更复杂)方法,首先使用rev命令反转文件路径,从第一个.中剪切,然后再次反转文件路径,如下所示:

filename=`rev <<

fileext=`rev <<

我从来没有见过那些三角支架<<

它们被称为"这里的字符串"(这里有更多信息),基本上它把输入作为一个字符串,并在程序读取stdin时将其馈送给程序。

如果您想使用Windows文件路径(在cygwin下)进行良好的播放,也可以尝试以下操作:

fname=${fullfile##*[/|\\]}

在Windows上使用bash时,这将解释反斜杠分隔符。

只是我想出的一个替代方法来提取一个扩展,使用这个线程中的文章和我自己更熟悉的小知识库。

ext="$(rev <<

注意:请建议我使用报价单;它对我有效,但我可能会错过一些关于它们正确使用的内容(我可能使用太多)。

您不需要一个单引号,您尝试这样做:rev <<< file.docx | cut -f1 -d. | rev,只是不带引号,也不带嵌套的子shell。另外,我认为上述方法根本行不通。

使用basename命令。它的主页在这里:http://unixhelp.ed.ac.uk/cgi/man-cgi?基名

他用的是basename,但这不是他的问题。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值