Correct me if this statement is wrong: All variables/parameters that defined inside a zsh script keep its persistent scope globally in current shell session.

If above statement is true, then to avoid messing around the current shell's environment variables / other zsh scripts. Should we put all variables/parameters of a zsh script to anonymous/local inner function if possible?

The possibilities can be counted as:

  1. We use that variables right away in that local scope => anonymous function
  2. Mark their scope by using maker always => inner func using always
  3. Mark but using rarely used traps to mark => inner func using traps

The question and the purpose is that all variables/parameters must local inside a zsh script and must be destroyed after used inside that zsh script.

EDIT: I did confuse about runing and sourcing shell script.

I want to source a script inside a script but try to keep minimizing affect of the sourcing script to mess the calling script's environment.

@Stéphane Chazelas did answer the question but I'd to make it clear as I understand, correct if I'm wrong.

Running a shell script inside a shell script ./script.zsh will invoke new shell to run the script then return exit code to the calling script.

Sourcing a shell script inside a shell script . ./script.zsh will create a sub-process of the current shell and any changes - define new variables, functions.. will be put in the current shell's environment, this is expected behavior because mostly user want to use them after sourcing process but you can exclude unwanted portions by using anonymous funcion like @Stéphane Chazelas mentioned in comment. With note that alias always comes up with global scope.


No, when you execute a script, your shell forks a new process in which the interpreter of that script is executed to interpret the content of that script.

Any variable assignment will only affect the shell variables of that shell invocation in that process. Once that process dies, the variables of the calling shell will not have been affected.

The only exception I know to that is with the fish shell when using set -U var value to define fish universal variables, where fish passes the variable value using some IPC mechanism between processes running fish and use permanent storage to retain the value of the variable when no fish process is running.

Now when you source a script (as opposed to execute it) with the . or source builtin command within your shell, then you tell your shell to interpret code in that script (there is no sub-process involved here, . ./script.zsh is similar to eval "$(<script.zsh)"). But then you generally only use source when you do want variable assignments there to affect your shell, like when sourcing environment files.

Now you can imagine scripts meant to be sourced in which you want some variables, functions, aliases... to be defined in the invoking shell, but some that are only helper variables that are not. And then yes, you could use an anonymous function with local scope like:

myfunc() echo hi # function meant to be defined for the invoker
myvar=value  # same for a variable

(){ local i # i variable local
  for i in foo bar
    alias $i='echo x' # alias defined globally

(note that zsh only implements local scope for variables and options, not for functions, aliases...)

|improve this answer|||||
  • I did confuse about running and sourcing shell script, did edit the post. – Tuyen Pham Sep 14 '18 at 8:34
  • Thanks for the clear explanation. The universal scope in Fish is interesting! – LeOn - Han Li Apr 1 '19 at 23:36

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.