Solved Removing duplicated $PATH

As topic states .. i have one path 3 times ( by accident ) and can not find how to remove.
Im using zsh shell for user account.
Thank You.
 
The man page has a FILES section that mentions a few possibilities:


I don’t mean that in an RTFM way - just saying it might be pointing at something worth checking.

e.g. do you have any .z<something> files in your home directory?
 
Can you post your user .zshrc & global /etc/csh.cshrc
What is the shell of the user as defined in /etc/passw
I added only 2 lines of code rest of it - standard:
Code:
neofetch

export PATH="$HOME/.local/bin/:$PATH"

i was installing qtile and i was taking example from my other laptop (FreeBSD in there as well ) so i wrote same line .. but i was having an issue with qtile so i deleted it and used git to install and wrote export PATH command with path location ( i believe i did it 2 times )
P.s. if i write $PATH in my terminal - i have 4 same paths :)
 
What does echo $PATH output?
Code:
/home/evo/.local/bin/:/home/evo/.local/bin/:/home/evo/.local/bin/:/home/evo/.local/bin/:/home/evo/.local/bin/:/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/sbin:/usr/local/bin:/home/evo/bin

Its like replicator - multiplying itself
 
I added only 2 lines of code rest of it - standard:
Where exactly did you add that line? In which file? If you execute that export PATH="$HOME/.local/bin/:$PATH" multiple times consecutively, it's going to add that /home/eve/.local/bin to the PATH each time. You then end up with multiple references to that path.
 
use this
Code:
[ ${PATH%%:*} = ${HOME}/.local/bin ] || export PATH="$HOME/.local/bin:$PATH"
assuming zsh will do posix expansions
 
use this
Code:
[ ${PATH%%:*} = ${HOME}/.local/bin ] || export PATH="$HOME/.local/bin:$PATH"
assuming zsh will do posix expansions
but it does not remove duplicates... i want to remove duplicated paths - which now i have 6 of them :)
 
I found this :
Code:
ZSH users

If you are a ZSH user and there are too many paths in your ~/.zshrc file, you can add the following at the end of your ~/.zshrc:

# .zshrc
typeset -U PATH

This prevents duplicates of PATH variables.

so now instead of :
Code:
/home/evo/.local/bin:/home/evo.local/bin/:/home/evo/.local/bin:/home/evo.local/bin/:/home/evo/.local/bin:/home/evo.local/bin/:/sbin:/bin:/usr/sbin:/usr/bin/usr/local/sbin/usr/local/bin:/home/evo/bin

it shows me:

Code:
/home/evo/.local/bin:/home/evo.local/bin/:/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/sbin:/usr/local/bin:/home/evo/bin
removed only few dupes and /home/evo/.local/bin: still is still posted twice.
 
It sounds like you're running zsh in a zsh multiple times. Each subshell will inherit the parent's exported variables, and ~/.zshrc is invoked every time you start zsh. Thus every subshell will add a /home/evo/.local/bin to the PATH variable.

Code:
       Commands	 are then read from $ZDOTDIR/.zshenv.  If the shell is a login
       shell, commands are read	from /etc/zprofile  and	 then  $ZDOTDIR/.zpro-
       file.   Then,  if  the  shell  is  interactive,	commands are read from
       /etc/zshrc and then $ZDOTDIR/.zshrc.  Finally, if the shell is a	 login
       shell, /etc/zlogin and $ZDOTDIR/.zlogin are read.
It's also possible you have that PATH line in ~/.zshrc and ~/.zprofile causing it to get executed twice.
 
See how this works?
Code:
dice@fbsd-test:~ % echo $SHELL
/bin/tcsh
dice@fbsd-test:~ % cat ~/.zshrc
export PATH="${HOME}/mypath:$PATH"
dice@fbsd-test:~ % echo $PATH
/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/sbin:/usr/local/bin:/home/dice/bin
dice@fbsd-test:~ % zsh
fbsd-test% echo $PATH
/home/dice/mypath:/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/sbin:/usr/local/bin:/home/dice/bin
fbsd-test% zsh
fbsd-test% echo $PATH
/home/dice/mypath:/home/dice/mypath:/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/sbin:/usr/local/bin:/home/dice/bin
fbsd-test% zsh
fbsd-test% echo $PATH
/home/dice/mypath:/home/dice/mypath:/home/dice/mypath:/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/sbin:/usr/local/bin:/home/dice/bin
 
It sounds like you're running zsh in a zsh multiple times. Each subshell will inherit the parent's exported variables, and ~/.zshrc is invoked every time you start zsh. Thus every subshell will add a /home/evo/.local/bin to the PATH variable.

Code:
       Commands     are then read from $ZDOTDIR/.zshenv.  If the shell is a login
       shell, commands are read    from /etc/zprofile  and     then  $ZDOTDIR/.zpro-
       file.   Then,  if  the  shell  is  interactive,    commands are read from
       /etc/zshrc and then $ZDOTDIR/.zshrc.  Finally, if the shell is a     login
       shell, /etc/zlogin and $ZDOTDIR/.zlogin are read.
It's also possible you have that PATH line in ~/.zshrc and ~/.zprofile causing it to get executed twice.
Is this because i typed zsh instead of source ~/.zshrc
 
Is this because i typed zsh instead of source ~/.zshrc
Because that will spawn a subshell that inherits the parent's PATH variable and executes ~/.zshrc, adding the directory again to the existing PATH. But even if you source the file it would still get added to the existing PATH (which already included that directory).

Code:
dice@fbsd-test:~ % echo $PATH
/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/sbin:/usr/local/bin:/home/dice/bin
dice@fbsd-test:~ % zsh
fbsd-test% source .zshrc
fbsd-test% echo $PATH
/home/dice/mypath:/home/dice/mypath:/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/sbin:/usr/local/bin:/home/dice/bin
fbsd-test% source .zshrc
fbsd-test% echo $PATH
/home/dice/mypath:/home/dice/mypath:/home/dice/mypath:/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/sbin:/usr/local/bin:/home/dice/bin
 
See how this works?
Code:
dice@fbsd-test:~ % echo $SHELL
/bin/tcsh
dice@fbsd-test:~ % cat ~/.zshrc
export PATH="${HOME}/mypath:$PATH"
dice@fbsd-test:~ % echo $PATH
/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/sbin:/usr/local/bin:/home/dice/bin
dice@fbsd-test:~ % zsh
fbsd-test% echo $PATH
/home/dice/mypath:/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/sbin:/usr/local/bin:/home/dice/bin
fbsd-test% zsh
fbsd-test% echo $PATH
/home/dice/mypath:/home/dice/mypath:/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/sbin:/usr/local/bin:/home/dice/bin
fbsd-test% zsh
fbsd-test% echo $PATH
/home/dice/mypath:/home/dice/mypath:/home/dice/mypath:/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/sbin:/usr/local/bin:/home/dice/bin
I see .. i typed zsh by accident ... .
Thank You.
 
One possible solution: Don't add things to the path if (a) they don't exist, and (b) if they are already on the path:

Code:
if [ -d $HOME/bin ] && ! echo $PATH | egrep -q  "(^|:)$HOME/bin($|:)" ; then
    export PATH=$HOME/bin:$PATH ; fi
(that syntax works both in bash and in zsh, and probably in all sh-based shells)
 
zshbuiltins(1):
Rich (BB code):
       typeset [ {+|-}AHUaghlmrtux ] [ {+|-}EFLRZip [ n	] ]
	       [ + ] [ name[=value] ...	]
       typeset -T [ {+|-}Uglrux	] [ {+|-}LRZp [	n ] ]
	       [ + | SCALAR[=value] array[=(value ...)]	[ sep ]	]
       typeset -f [ {+|-}TUkmtuz ] [ + ] [ name	... ]
	      Set or display attributes	and values for shell parameters.
[...]
	      -U     For arrays	(but not for associative  arrays),  keep  only
			     the  first	occurrence of each duplicated value.  This may
			     also be set for tied parameters (see -T)  or  colon-sepa-
			     rated special parameters like PATH	or FIGNORE, etc.  Note
			     the flag takes effect on assignment, and the type of  the
			     variable  being  assigned	to is determinative; for vari-
			     ables with	shared values it is therefore  recommended  to
			     set  the  flag  for all interfaces, e.g. `typeset -U PATH
			     path'.

			     This flag has a different meaning when used with -f;  see
			     below.

Chapter 2.5.11: Path from A User's Guide to ZSH describes it with examples; from there, in .zshenv:
You could use:
Code:
for dir in ~/bin ~/progs/bin; do
    if [[ -z ${path[(r)$dir]} ]]; then
      path=($dir $path)
    fi 
done
However, given zhs' specific properties, there is a more compact form:
Code:
typeset -U path
path=(~/bin ~/progs/bin $path)
Alternatively, you could set the path in .zshrc (only for interactive shells!).



edit - amended (see also message below):
Code:
If you are a ZSH user and there are too many paths in your ~/.zshrc file, you can add the following at the end of your ~/.zshrc:

# .zshrc
typeset -U PATH

The two following settings both work:
Code:
typeset -U PATH
PATH="$HOME/.local/bin/:$PATH"
Code:
typeset -U path
path=(~/.local/bin/ $path)

Using either option:
  1. typeset -U path in combination with path=(~/.local/bin/ $path)
  2. typeset -U PATH in combination with PATH="$HOME/.local/bin/:$PATH"
has the same effect* because path and PATH are tied parameters, that is: when you change one the other changes accordingly. In zsh(1), path and PATH are special: they are tied by default and PATH is exported by default.

For example, without export:
Code:
% typeset -U PATH
% PATH="$HOME/.local/bin/:$PATH"
you should be able to see the active settings as follows:
Code:
% typeset -p PATH
export -UT PATH path=( /home/evo/.local/bin /sbin /bin /usr/sbin /usr/bin /usr/local/sbin /usr/local/bin /home/evo/bin )
___
* In general, the effect of uniqueness is only enforced for the specified parameter: typeset -U PATH only enforces uniqueness for PATH. To enforce the same uniqueness behaviour for the scalar PATH and the array path it is recommended to use both:
Rich (BB code):
typeset -U path PATH
PATH="$HOME/.local/bin/:$PATH"
 
Last edited:
I found this :
Code:
typeset -U PATH
This prevents duplicates of PATH variables.

When I look at your examples of PATH then typeset -U did its job and made its parts unique:
so now instead of :
Rich (BB code):
/home/evo/.local/bin:/home/evo.local/bin/:/home/evo/.local/bin:/home/evo.local/bin/:/home/evo/.local/bin:/home/evo.local/bin/:/sbin:/bin:/usr/sbin:/usr/bin/usr/local/sbin/usr/local/bin:/home/evo/bin
it shows me:
Rich (BB code):
/home/evo/.local/bin:/home/evo.local/bin/:/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/sbin:/usr/local/bin:/home/evo/bin
removed only few dupes and /home/evo/.local/bin: still is still posted twice.
 
Back
Top