For example, I create 32768 directories named 0,1,2,...32767.

I want to randomly choose one as the path every time I run a command.

So I change $PATH to $PATH:/blabla/$RANDOM, but it won't work because $RANDOM is evaluated immediately.

How can I delay the evaluation?

  • 1
    Store the actual PATH into a PATHTEMP. export the PATH just before executing your command as export PATH=$PATHTEMP:/blabla/$RANDOM. – neuron Aug 7 '15 at 7:36
  • @Neuron looking for an automatic solution – sqd Aug 7 '15 at 7:39
  • 1
    Can you paste your script & the expected behaviour ? – neuron Aug 7 '15 at 7:39
  • @Neuron I was just wondering if this is possible. Thanks anyway :) – sqd Aug 7 '15 at 7:41
  • Shells don't do "lazy evaluation", period. – vonbrand Aug 7 '15 at 12:31

This isn't a capability of any of the common shells.

Recent versions of ATT ksh have a unique feature among shells called discipline functions. You can execute custom code when a variable is accessed, and if you set .sh.value to a different value, that value is used instead of the value of the variable.

function PATH.get { .sh.value=$PATH:/blabla/$RANDOM; }

However even this feature won't help you for PATH since it only triggers when a variable is used by the script, not by internal uses of PATH inside the shell.

If you want that for the last PATH element, and you're using bash or zsh, you can use their command-not-found feature to invoke custom code if a command is not found. In bash:

command_not_found_handle () {
  command "/blabla/$RANDOM/$@"

In zsh:

command_not_found_handler () {
  /blabla/$RANDOM/$1 "$@[2,$#]"

Apart from these cases, there's no shell feature that'll help you. In any case, no shell feature will help you for programs that are not invoked by a shell.

You could use LD_PRELOAD to override the execlp, execvp and execvpe library functions to do something different from breaking up PATH into colon-separated pieces and interpreting each of them as a directory. See Redirect a file descriptor before execution for an LD_PRELOAD example.

Alternatively, you could put a PATH entry on a FUSE filesystem that implements a stacked filesystem that makes the given path correspond to a variable underlying directory. This will work for programs that just call execve with each PATH element until one works, but it'll confuse programs that first traverse the PATH entries looking for existing, executable files and then execute the one that is found.

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.