Zsh Mailing List Archive
Messages sorted by: Reverse Date, Date, Thread, Author

Re: Setting paths with ~'s in values.



On Feb 12,  2:17pm, Larry P . Schrof wrote:
> Subject: Setting paths with ~'s in values.
> ---
> # Generate a nice-looking path, including only directories that exist.
> for t_path in "${(f)$(<${HOME}/.zpaths)}"
> do
>     if 
>         [[ -d $t_path ]]
>     then 
>         PATH=${PATH}:${~t_path}
>     fi
> done
> 
> PATH=${PATH[2,-1]}	# Nuke the leading ':'
> ---
> 
> From the man page, I was under the impression that putting the ~
> before the variable would expand the '~' in each of those paths.

No.  What the ~ in ${~t_path} does is make the filename *generation*
characters in the value "available" to be processed later, when regular
filename generation takes place (see the "Expansion" part of the info
docs, or "man zshexpn").  This doesn't apply to filename *expansion*,
which is the ~ character.  Even if it did, expansion/generation isn't
done on the right-hand-side of scalar parameter assignments.

The preferred solution to this problem is to use the $path array, which
is automatically converted by zsh to a colon-separated string which is
stuffed into the $PATH environment.  Filename generation and expansion
is done in array assignments -- but that still doesn't expand the ~ .
So you need an additional "eval" for that, which means you don't need
the ~ any more.

Also, you don't need to split the .zpaths file by lines with ${(f)...}
unless some of your paths contain spaces (in which case the eval gets
more complicated too).

A direct translation would thus be:

  for t_path in $(<${HOME}/.zpaths)
  do
      if 
          [[ -d $t_path ]]
      then 
          eval path=\( $path $t_path \)
      fi
  done

and you don't need the extra step of removing the leading colon.  But
there's a better, faster, smarter way to do the same thing:

  eval path=\( ${^$(<${HOME}/.zpaths)}'(|)(/)' \)

Here, the ${^...} takes the place of the "for" loop, the (/) tests a
glob pattern to see if it refers to a directory, and the (|) turns each
of the lines from .zpaths into an equivalent glob pattern so that (/)
test is applied.  The quotes and backslashes just make sure that the
globbing and array assignment steps are delayed until the "eval" runs.



Messages sorted by: Reverse Date, Date, Thread, Author