2

I have a couple of scripts /tmp/foo/bar.sh and /tmp/foo/baz.sh, the look like this:

# /tmp/foo/bar.sh

alias -g __FILE__='${(%):-%x}'
alias -g __DIR__='${${(%):-%x}%/*}'

printf "sourcing %s\n" __FILE__
printf "about to source %s/baz.sh\n" __DIR__

. /tmp/foo/baz.sh

. $( printf "%s/baz.sh" __DIR__ ) # succeeds
. __DIR__"/baz.sh"                  # fails
# /tmp/foo/baz.sh

printf "sourcing %s\n" __FILE__

The first script, /tmp/foo/bar.sh, defines a couple of global (-g) aliases as incantations that should expand (to a first approximation!) to the current script's (invocation) path, and it's containing directory. Then it uses these aliases as arguments in a couple of printf commands. Finally, it sources the second script, /tmp/foo/baz.sh, in three different ways:

  1. using the literal path to the second script;
  2. using the __DIR__ alias indirectly, through a printf command substitution;
  3. using the __DIR__ alias directly.

Here's what I get when I source the first script:

% (/usr/bin/env -i zsh -fc '. /tmp/foo/bar.sh')
sourcing /tmp/foo/bar.sh
about to source /tmp/foo/baz.sh
sourcing /tmp/foo/baz.sh
sourcing /tmp/foo/baz.sh
/tmp/foo/bar.sh:.:11: no such file or directory: __DIR__/baz.sh

(The song-and-dance with /usr/bin/env is my attempt to source /tmp/foo/bar.sh in as barebones an environment as possible.)

It appears that if __DIR__ is immediately followed by /baz.sh, then it is not recognized as an alias, which is not unreasonable. The form $( printf "%s/baz.sh" __DIR__ ) gets around this problem, but its length and convolutedness pretty much of the benefit of using an alias in the first place.

Is there a more convenient way to build the path to the second string using the __DIR__ alias?

More generally, is there some general "syntactic trick" to alert the parser that a specific sequence of characters should be treated like an alias? My hope is to make such a global alias more closely resemble the behavior of a simple (i.e. one-line, no arguments, etc.) C pre-processor macro. An example of the kind of "syntatic trick" I have in mind is something like the following (none of which work):

. {__DIR__}/baz.sh
. __DIR__"/baz.sh"
1

There's a feature that allows a string to be substituted by another string with just one extra character:

__FILE__='${(%):-%x}'
__DIR__='${${(%):-%x}%/*}'
. $__DIR__/baz.sh

If you really don't want to define a variable, an alternative is to define a named directory, which is only expanded after a tilde at the beginning of a word. This works in your example but might not generalize to all the cases where you want it.

hash -d __FILE__='${(%):-%x}'
hash -d __DIR__='${${(%):-%x}%/*}'
. ~__DIR__/baz.sh
0

OK, I found an adequate solution, illustrated below

# /tmp/foo/bar.sh

alias -g __FILE__='echo "${(%):-%x}"'
alias -g __DIR__='echo "${${(%):-%x}%/*}"'

printf "sourcing %s\n" $(__FILE__)
printf "about to source %s/baz.sh\n" $(__DIR__)

. $(__DIR__)/baz.sh               # succeeds

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.