shellterminalzsh

zsh get extension with dot in one line (ideally one expansion)


How can I get the zsh extension with the dot included?

Example inputs and outputs desired:

I know I could test "Does this string have an extension?" with an if-statement, then if it does have an extension I can use ${var:e} parameter expansion, but this is very verbose.

I'm sure there must be a shorter way to get the end of a file name.

The reason this is useful to me is so that I can generate new file names that have the same extensions as existing file names, even if those existing file names don't have extensions. I had previously tried

"${existing:r}-$count.${existing:e}"

But that doesn't work for existing file names that don't have extensions (it adds a dot at the end)


Solution

  • One possibility, based on this answer:

    ext=${fname#$fname:r}
    

    The :r (root) expansion modifier will remove the dot and extension from the path. The code uses the ${name#pattern} expansion to reverse that, and keep the part that was deleted. Some examples:

    (){ for f; printf "%-7s -> '%s'\n" $f ${f#$f:r} } \
        'one.two' 'none' 'just.' '/with/a dir.part/a b.c d'
    #=> one.two -> '.two'
    #=> none    -> ''
    #=> just.   -> '.'
    #=> /with/a dir.part/a b.c d -> '.c d'
    

    Building a filename:

    existing=file.ext; count=22
    newName="${existing:r}-${count}${existing#$existing:r}"
    typeset -p newName
    #=> typeset newName=file-22.ext