2

While looking online on how to get a file's extension and name, I found:

filename=$(basename "$fullfile")
extension="${filename##*.}"
filename="${filename%.*}

What is the ${} syntax...? I know regular expressions but "${filename##*.}" and "${filename%.*} escape my understanding.

Also, what's the difference between:

filename=$(basename "$fullfile")

And

filename=`basename "$fullfile"`

...? Looking in Google is a nightmare, because of the strange characters...

Merc
  • 16,277
  • 18
  • 79
  • 122
  • 2
    My Google works: [Shell Parameter Expansion](https://www.gnu.org/software/bash/manual/bashref.html#Shell-Parameter-Expansion). – e0k Feb 27 '16 at 05:24
  • @e0k: The link is helpful, but the OP's point was that if you don't know a feature's _name_, it's hard to google it by the symbols it involves alone. – mklement0 Feb 27 '16 at 05:49
  • 1
    Searching for `##` in the man page takes you directly to the relevant documentation. – chepner Feb 27 '16 at 13:29

2 Answers2

2

As @e0k states in a comment on the question the ${varname...} syntax is Bash's parameter (variable) expansion. It has its own syntax that is unrelated to regular expressions; it encompasses a broad set of features that include:

  • specifying a default value
  • prefix and postfix stripping
  • string replacement
  • substring extraction

The difference between `...` and $(...) (both of which are forms of so-called command substitutions) is:

  • `...` is the older syntax (often called deprecated, but that's not strictly true).
  • $(...) is its modern equivalent, which facilitates nested use and works more intuitively when it comes to quoting.
  • See here for more information.
mklement0
  • 382,024
  • 64
  • 607
  • 775
2

The ${filename##*.} expression is parameter expansion ("parameters" being the technical name for the shell feature that other languages call "variables"). Plain ${varname} is the value of the parameter named varname, and if that's all you're doing, you can leave off the curly braces and just put $varname. But if you leave the curly braces there, you can put other things inside them after the name, to modify the result. The # and % are some of the most basic modifiers - they remove a prefix or suffix of the string that matches a wildcard pattern. # removes from the beginning, and % from the end; in each case, a single instance of the symbol removes the shortest matching string, while a double symbol matches the longest. So ${filename##*.} is "the value of filename with everything from the beginning to the last period removed", while ${filename%.*} is "the value of filename with everything from the last period to the end removed".

The backticks syntax (`...`) is the original way of doing command substitution in the Bourne shell, and has since been borrowed by languages like Perl and Ruby to incorporate calling out to system commands. But it doesn't deal well with nesting, and its attempt to even allow nesting means that quoting works differently inside them, and it's all very confusing. The newer $(...) syntax, originally introduced in the Korn shell and then adopted by Bash and zsh and codified by POSIX, lets quoting work the same at all levels of a nested substitution and makes for a nice symmetry with the ${...} parameter expansion.

Mark Reed
  • 91,912
  • 16
  • 138
  • 175
  • Thank you Mark. I am using Bash the way I used Bourne Shell back in the day, when I learned it with AIX. I guess it's time for me to look at it again properly! – Merc Feb 28 '16 at 02:23