Search code examples
zsh

Combine basename with default value on parameter


I want to write a zsh script (zsh 5.8.1), which accepts a single, optional parameter which is a file path. I want to derive a variable with the following properties:

  1. If the parameter is non-empty, the variable should hold the basename of the file
  2. Otherwise, the variable should be empty

Additional restriction: The shell script should run with set -u.

I don't see how I can do both conditions in one go.

The first condition can easily be fulfilled by:

var=$1:t

but this produces an error (due to set -u), if there is no parameter.

The second condition can be fulfilled by:

var=${1:-}

and I could combine them in two statements:

var=${1:-}
var=$var:t

Can this be done with a single assignment? I tried:

var=${ ${1:-}:t }

but this produces the error zsh: bad substitution.


Solution

  • Nested expansions are supported in zsh, but usually as a single token (i.e., no spaces):

    #!/usr/bin/env zsh -u
    # -u: NO_UNSET - error if referencing a variable that has not been set
    var=${${1:-}:t}
    typeset -p var
    

    Testing:

    > ./tst 'dir/lvl2/file.txt'
    typeset var=file.txt
    > ./tst abcdefg
    typeset var=abcdefg
    > ./tst
    typeset var=''