zsh: typeset -Ug PATH
自分の zshrc 内では、$PATH
の重複を排除するために typeset -U PATH
と書いていた。
普段はこれで上手く行くが、関数内で source ~/.zshrc
すると zshrc 内でエラーが沢山出た。
$ cat ~/.zshrc ... function reload_zshrc { source ~/.zshrc } ... $ reload_zshrc ... zsh:17: command not found: find zsh:17: command not found: find ...
source
内では command not found
となっているが、 reload_zshrc
した後も $PATH
は変わらず、コマンドも使えていた。
また、関数を経由せずに source ~/.zshrc
とした時は正常に動いていた。
原因
これは、typeset
は関数内の場合、 ローカル変数を作成 し、関数が終わったら unset
するという挙動によるものである。
Except as noted below for control flags that change the behavior, a parameter is created for each name that does not already refer to one. When inside a function, a new parameter is created for every name (even those that already exist), and is unset again when the function completes. See `Local Parameters' in zshparam(1). The same rules apply to special shell parameters, which retain their special attributes when made local.
Ubuntu Manpage: zshbuiltins - zsh built-in commands
なので、 reload_zshrc
の中で typset -U PATH
することで PATH
の内容が初期化されてしまい、 command not found
となっていた。
echo $PATH # /usr/local/bin:/bin: ... typeset -U PATH echo $PATH # (Empty output)
対処
これを防ぐためには、 typset -g
で global scope の PATH
を使用するようにする。
-g The -g (global) means that any resulting parameter will not be restricted to local scope. Note that this does not necessarily mean that the parameter will be global, as the flag will apply to any existing parameter (even if unset) from an enclosing function. This flag does not affect the parameter after creation, hence it has no effect when listing existing parameters, nor does the flag +g have any effect except in combination with -m (see below).
Ubuntu Manpage: zshbuiltins - zsh built-in commands
echo $PATH # /usr/local/bin:/bin: ... typeset -gU PATH echo $PATH # /usr/local/bin:/bin: ...