1

I would like to use parameter substitution to compute a path based on

  1. a variable being defined
  2. a first default directory to be used if it exists
  3. a file inside the $HOME directory to be used if neither of 1 or 2 are available.

The variable (#1) and the file in $HOME (#3) are easy:

${KEEPER_HOME:-$HOME/.keeper}

But is there a parameter/variable substitution syntax in Zsh for #2? If we imagined that || did this, I would be looking for something like this:

${KEEPER_HOME:-$HOME/.config/keeper||$HOME/.keeper}

Of course I can do it with test inside $(...) but I am hoping that something more concise and readable exists.

iconoclast
  • 21,213
  • 15
  • 102
  • 138
  • For (2), you need to do a test for existence, and I don't see how this can be done implicitly by a parameter expansion. – user1934428 Apr 07 '21 at 06:28

2 Answers2

2

You can use the null glob qualifier to check for this existence of files (including directories):

% print /etc(N)
/etc
% print /foo(N)

This works inside parameter expansions, too, when passed as arguments:

% print ${:-/etc(N)}
/etc
% print ${:-/foo(N)}

If you want to use null glob when assigning a scalar, then you will need to use $~glob substitution when expanding the parameter:

% tmp=${:-/foo(N)} 
% print $tmp
/foo(N)
% print $~tmp

% 

Alternatively, you could use an array instead:

% tmp=( /foo(N) )
% print $tmp

%

However, for your exact case, I’d recommend using an if statement, since it makes the code easier to read:

# Check if string is zero.
if [[ -z $KEEPER_HOME ]]; then
  local default=${XDG_CONFIG_HOME:-~/.config}/keeper

  # Check if dir exists.
  if [[ -d $default ]]; then
    KEEPER_HOME=$default
  else
    KEEPER_HOME=~/.keeper
  fi
fi
Marlon Richert
  • 5,250
  • 1
  • 18
  • 27
1

This only uses parameter expansions, but it's two lines:

glob=($HOME/.config/keeper(N/))
result=${KEEPER_HOME:-${glob:-$HOME/.keeper}}

The glob= line uses the / glob qualifier to check for the directory. The N qualifier turns on nullglob, so the variable will be empty if the directory doesn't exist.

There may be a way to move the globbing into the nested parameter expansion, but I haven't found one yet.

Gairfowl
  • 2,226
  • 6
  • 9
  • In Zsh, the coding convention is to use UPPERCASE only for scalar environment variables. Don't use uppercase for local parameters or arrays. – Marlon Richert Apr 07 '21 at 08:39