Linux 在bash中提取没有路径和扩展名的文件基名

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2664740/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-03 19:57:53  来源:igfitidea点击:

Extract file basename without path and extension in bash

linuxbashunixfilenames

提问by neversaint

Given file names like these:

给定文件名,如下所示:

/the/path/foo.txt
bar.txt

I hope to get:

我希望得到:

foo
bar

Why this doesn't work?

为什么这不起作用?

#!/bin/bash

fullfile=
fname=$(basename $fullfile)
fbname=${fname%.*}
echo $fbname

What's the right way to do it?

正确的做法是什么?

采纳答案by ghostdog74

You don't have to call the external basenamecommand. Instead, you could use the following commands:

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

$ s=/the/path/foo.txt
$ echo "${s##*/}"
foo.txt
$ s=${s##*/}
$ echo "${s%.txt}"
foo
$ echo "${s%.*}"
foo

Note that this solution should work in all recent (post 2004) POSIXcompliant shells, (e.g. bash, dash, ksh, etc.).

请注意,这个解决方案应该在所有近期的(工作后2004年POSIX兼容的外壳(例如bashdashksh等)。

Source: Shell Command Language 2.6.2 Parameter Expansion

来源:Shell Command Language 2.6.2 参数扩展

More on bash String Manipulations: http://tldp.org/LDP/LG/issue18/bash.html

更多关于 bash 字符串操作:http: //tldp.org/LDP/LG/issue18/bash.html

回答by Michael Aaron Safyan

The basenamecommand has two different invocations; in one, you specify just the path, in which case it gives you the last component, while in the other you also give a suffix that it will remove. So, you can simplify your example code by using the second invocation of basename. Also, be careful to correctly quote things:

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

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

回答by Bandicoot

Use the basename command. Its manpage is here: http://unixhelp.ed.ac.uk/CGI/man-cgi?basename

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

回答by higuaro

Here is another (more complex) way of getting either the filename or extension, first use the revcommand to invert the file path, cut from the first .and then invert the file path again, like this:

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

filename=`rev <<< "" | cut -d"." -f2- | rev`
fileext=`rev <<< "" | cut -d"." -f1 | rev`

回答by vincent gravitas

If you want to play nice with Windows file paths (under Cygwin) you can also try this:

如果你想很好地使用 Windows 文件路径(在 Cygwin 下),你也可以试试这个:

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

This will account for backslash separators when using BaSH on Windows.

在 Windows 上使用 BaSH 时,这将考虑反斜杠分隔符。

回答by kom lim

A combination of basename and cut works fine, even in case of double ending like .tar.gz:

basename 和 cut 的组合效果很好,即使在双结尾的情况下也是如此.tar.gz

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

Would be interesting if this solution needs less arithmetic power than Bash Parameter Expansion.

如果此解决方案需要比 Bash Parameter Expansion 更少的算术能力,那将会很有趣。

回答by Diomoid

Just an alternative that I came up with to extract an extension, using the posts in this thread with my own small knowledge base that was more familiar to me.

只是我想出的一种替代方法来提取扩展名,使用此线程中的帖子以及我自己更熟悉的小型知识库。

ext="$(rev <<< "$(cut -f "1" -d "." <<< "$(rev <<< "file.docx")")")"

Note: Please advise on my use of quotes; it worked for me but I might be missing something on their proper use (I probably use too many).

注意:请告知我对报价的使用;它对我有用,但我可能在正确使用时遗漏了一些东西(我可能使用了太多)。

回答by sancho.s ReinstateMonicaCellio

Here are oneliners:

这里是单线:

  1. $(basename "${s%.*}")
  2. $(basename "${s}" ".${s##*.}")
  1. $(basename "${s%.*}")
  2. $(basename "${s}" ".${s##*.}")

I needed this, the same as asked by bongbang and w4etwetewtwet.

我需要这个,就像 bongbang 和 w4etwetewtwet 所问的那样。

回答by agc

Pure bash, no basename, no variable juggling. Set a string and echo:

纯粹的bash,不basename,没有可变的杂耍。设置一个字符串和echo

p=/the/path/foo.txt
echo "${p//+(*\/|.*)}"

Output:

输出:

foo

Note: the bashextgloboption must be "on", (Ubuntusets extglob"on" by default), if it's not, do:

注意:bashextglob选项必须为“on”,(Ubuntu默认将extglob设置“on”),如果不是,请执行以下操作:

shopt -s extglob


Walking through the ${p//+(*\/|.*)}:

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

  1. ${p-- start with $p.
  2. //substitute every instance of the pattern that follows.
  3. +(match one or moreof the pattern listin parenthesis, (i.e.until item #7 below).
  4. 1stpattern: *\/matches anything before a literal "/" char.
  5. pattern separator |which in this instance acts like a logical OR.
  6. 2ndpattern: .*matches anything after a literal "." -- that is, in bashthe "." is just a period char, and nota regex dot.
  7. )end pattern list.
  8. }end parameter expansion. With a string substitution, there's usually another /there, followed by a replacement string. But since there's no /there, the matched patterns are substituted with nothing; this deletes the matches.
  1. ${p-- 以$p开头。
  2. //替换后面的模式的每个实例。
  3. +(匹配一个或多个所述的模式列表中括号(即,直到下面项#7)。
  4. 第一种模式:*\/匹配文字“ /”字符之前的任何内容。
  5. 模式分隔符|在这种情况下就像一个逻辑 OR
  6. 第二种模式:.*匹配文字 " ."之后的任何内容——也就是说,在bash" ." 中只是一个句点字符,而不是正则表达式 dot
  7. )结束模式列表
  8. }结束参数扩展。对于字符串替换,通常会有另一个/替换字符串,然后是替换字符串。但是因为那里没有/,匹配的模式被替换为空;这将删除匹配项。

Relevant man bashbackground:

相关man bash背景:

  1. pattern substitution:
  1. 模式替换
  ${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.
  ${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.
  1. extended pattern matching:
  1. 扩展模式匹配
  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
  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