How to remove permanently a path from the fish $PATH? - linux

This question has already been asked, and answered here: https://superuser.com/a/940041/293429
However, the provided solution: executing set -e PATH[<index-of-the-path-to-be-removed] only applies to the running instance and is not valid universally.
After executing that command, if one executes echo $PATH the previously removed paths will occur again.
One way to completely reset the path is to execute: set -U fish_user_paths, but it is unclear to me that what it does.
The real trick would be to find out how to remove a path which has been manually added and make it available globally -- not only for the current instance?

There's two ways to do this, and which one is valid depends on how the path got into $PATH.
It is possible to add directories to $PATH via e.g. set PATH $PATH /some/dir. At least by default, PATH is a global variable, which means it is per-session. That means to change something from $PATH, either remove it from where it is added (which is likely outside of fish since it inherits it), or put the set -e call in your ~/.config/fish/config.fish so it will be executed on every start.
There is also $fish_user_paths, which is a universal variable (meaning it carries the same value across fish sessions and is synchronized across them). On startup and whenever fish_user_paths is modified, fish adds it to $PATH. If the offending directory is added here, execute set -e fish_user_paths[index] once (e.g. in an interactive session).
set -e fish_user_paths would remove the entire variable (while set -U fish_user_paths would clear it) which would also work but would also remove all other paths

Related

How to permanently set env across every session in fish shell?

I install the cargo building environment.
I use cargo install exa to install exa (an alternatives of command ls).
Executable file is put in $HOME/.cargo/bin.
I use fish shell set -gx PATH $PATH $HOME/.cargo/bin, and then I can use command exa on current session.
But when I open a new session, I cannot execute exa unless set -gx ... again.
I look in the options gx:
--global -g (Make variable scope global)
--export -x (Export variable to subprocess)
Does not global mean every session? Could someone help me pls?
Doesnot global means every session?
It doesn't. It's "global" as opposed to "local". From the fish documentation:
Global variables are specific to the current fish session, and will never be erased unless explicitly requested by using set -e.
In general, what you want is to just put the set -gx into ~/.config/fish/config.fish. That's fish's configuration file.
Fish also has "universal" variables, which are stored persistently, but they interact awkwardly with exporting so I wouldn't recommend it.
For $PATH specifically, fish offers the fish_user_paths variable that it adds automatically, so you can run
set -U fish_user_paths $fish_user_paths $HOME/.cargo/bin
once, interactively, and fish will take care of it. This is a universal variable, but fish takes care to add it to $PATH when necessary (for each component it checks if it's already there and such). Do not put this into config.fish, or it will add one $HOME/.cargo/bin every time you start a fish, and so it would balloon the variable.
To recap:
For global variables, put the set statement into config.fish
For universal variables, execute it manually
For $PATH, use $fish_user_paths for your customizations

Can't find who sets http_proxy environment variable on Ubuntu

I'm on Ubuntu 16.10,
When running in terminal:
env | grep proxy
I get:
https_proxy=https://127.0.0.1:8888/
http_proxy=http://127.0.0.1:8888/
I can't find who sets these environment variables.
I've tried all the answers here and could not find anything.
Tried different shells / terminals. Variables are always there.
Any idea what else can it be?
No luck in checking all the usual suspects? Then it's time to use the big gun:
find /etc $HOME /usr/local -type f | xargs grep -E 'https?_proxy'
Run this as root. Add directories to your liking.
An environment variable in your current shell can only be set in the parent process, or in a file sourced by your shell. I would start by turning on the shell trace in the respective rc-files which are sourced when you log in, in your home directory. This is also the place where I would verify whether the environment variables is already set at this point (which would mean that it was set by the global initialization process, for instance in the rc files which reside in /etc). Now log in and check the output.
If the environment variable is already set initially, you can't do much except bugging your admin that he should remove it (which probably won't work). If it is not set initially, you need to look through the output of the shell trace, until you either find the point, where the variable is set, or where you see that some malicious script turns off the trace.
Since you didn't give any information, which shell you are using, I can't go into deeper detail.
In my case those env variables were set by Fiddler web debugger and I was able to remove them manually by editing ~/.bashrc file. There are 2 lines with export http(s)_proxy... located at the end of this file. Hope that it helps!

Setting a part of a PWD as a prompt and keeping a variable updated

I'm using tcsh, and I'm trying to set a part of the PWD to appear always in the prompt (so I will always know in which "parent" directory I am).
I managed to extract the needed part of the prompt in the following way, and it works fine (I call it MyTreePath):
set MyTreePath=`echo $PWD | awk '{... print whichTree}'`
I've added the code above to my .tcshrc and I've added %$MyTreePath to my set prompt line in .tcshrc.
The problem is that once the shell is opened, the MyTreePath doesn't change, even if I'm going to a totally different path.
How to keep a variable that appears in the prompt updated?
Use the magical cwdcmd alias! It is used for defining a command which executes everytime the cwd changes. In your case, you need to updated your variable.
From the manpage:
The beepcmd, cwdcmd, periodic, precmd, postcmd, and jobcmd Special
aliases can be set, respectively, to execute commands when the
shell wants to ring the bell, when the working directory changes,
every tperiod minutes, before each prompt, before each command gets
executed, after each command gets executed, and when a job is started
or is brought into the foreground.
Here's a quick example:
alias cwdcmd 'set FOO=`pwd`'
set prompt='%$FOO >>> '
field testing:
cd /
/ >>> cd dev
/dev >>>
So all that's left is to replace pwd in the alias above with your own command.
For more info and other magic aliases, see here.

turning on / off environment variables

I have been trying to set the $PATH environment variable to point to different paths as I need them, but I have run into some issues.
The main thing is that when I set the PATH to point to my service that I need, I want it to stay that way in all subsequent bash shells. That is, when I open another bash shell it will be set there as well, until I decide to switch it back. And when I switch the PATH back to its original value. I want it to stay that way.
I added a small script to my .bashrc, I also tried doing a separate script that will change environment variables. But the problem stays: If I open a new bash shell, it inherits the default environment variables and the default PATH.
I am setting those to enable the use of a daemon service. I tried turning on/off the service itself. That does not work because the paths have to be changed or else the shell would try to use those environment paths, but the service being off it will just hang.
I tried running a small C program wrapper to do those things but I ran into the same issue.
In order for environment variable to exist across shell sessions you will need to place those variables into a shell configuration file. This is usually done in either ~/.bashrc or ~/.profile (if you are using Bash). For example, in my ~/.profile file I have:
export PATH=/opt/local/bin:/opt/local/sbin:$PATH
I can add to that path as much as I want. The $PATH variable at the end will append whatever is current in the path.
If you need scripts to be able to access the variables, you should put the PATH into the .bashrc file. (what is the difference between .bashrc and .profile)
If you make a change to one of your shell configuration files, the changes will not be in effect until those files are used again. Those files are only used when the shell is first initialized. In order to make changes take effect, you need to log out and back in, or open a new shell and close the old, or source the file that you made changes to.
$ vim ~/.bashrc (edit the file)
$ source ~/.bashrc (then reinitialize the shell with the file)
If you only need a variable to be available in the current shell and any subprocesses, using export would be all you need.
You might also be interested in this snippet. It reloads the .bashrc in any shell, whenever it is modified. (After re-editing the .bashrc file, press (or run a command) to cause the new .bashrc to be reloaded.)
# Make sure our version of the .bashrc file is up-to-date, or reload it.
chk_bashrc_timestamp () {
if [[ "$_BASHRC_TIMESTAMP" -lt "$(get_file_timestamp "$HOME/.bashrc")" ]]; then
echo >&2 "Reloading .bashrc..."
. ~/.bashrc
fi
}
_BASHRC_TIMESTAMP=$(date +%s)
PROMPT_COMMAND=chk_bashrc_timestamp
The only difficulty is, you must not use $PATH in the definition of PATH, or it will repeat the whole PATH each time it is needed:
Use
SYSPATH="/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin"
PATH="$HOME/bin:$SYSPATH:/opt/mystuff"
instead of
PATH="$HOME/bin:$PATH:/opt/mystuff"
I have used this with much satisfaction in my own .bashrc, except that I have protected my PATH from reloading each time by setting it in an if statement. (You may find you have other things you need to protect this way.)
if _BASHRC_WAS_RUN 2>/dev/null; then
:;
else # Stuff that only needs to run the first time we source .bashrc.
# Useful to allow resourcing new changes
export PATH="$HOME/bin:$HOME/.cabal/bin: ..."
alias _BASHRC_WAS_RUN=true
fi

Adding a new entry to the PATH variable in ZSH

I'm using zsh terminal, and I'm trying to add a new entry (/home/david/pear/bin) to the PATH variable. I don't see a reference to the PATH variable in my ~/.zshrc file, but doing echo $PATH returns:
/usr/lib/lightdm/lightdm:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games
So I know that the path variable is being set somewhere. Where is the PATH variable set / modified for the zsh terminal?
Actually, using ZSH allows you to use special mapping of environment variables. So you can simply do:
# append
path+=('/home/david/pear/bin')
# or prepend
path=('/home/david/pear/bin' $path)
# export to sub-processes (make it inherited by child processes)
export PATH
For me that's a very neat feature which can be propagated to other variables.
Example:
typeset -T LD_LIBRARY_PATH ld_library_path :
Here, add this line to .zshrc:
export PATH=/home/david/pear/bin:$PATH
EDIT: This does work, but ony's answer above is better, as it takes advantage of the structured interface ZSH provides for variables like $PATH. This approach is standard for bash, but as far as I know, there is no reason to use it when ZSH provides better alternatives.
You can append to your PATH in a minimal fashion. No need for
parentheses unless you're appending more than one element. It also
usually doesn't need quotes. So the simple, short way to append is:
path+=/some/new/bin/dir
This lower-case syntax is using path as an array, yet also
affects its upper-case partner equivalent, PATH (to which it is
"bound" via typeset).
(Notice that no : is needed/wanted as a separator.)
Common interactive usage
Then the common pattern for testing a new script/executable becomes:
path+=$PWD/.
# or
path+=$PWD/bin
Common config usage
You can sprinkle path settings around your .zshrc (as above) and it will naturally lead to the earlier listed settings taking precedence (though you may occasionally still want to use the "prepend" form path=(/some/new/bin/dir $path)).
Related tidbits
Treating path this way (as an array) also means: no need to do a
rehash to get the newly pathed commands to be found.
Also take a look at vared path as a dynamic way to edit path
(and other things).
You may only be interested in path for this question, but since
we're talking about exports and arrays, note that
arrays generally cannot be exported.
You can even prevent PATH from taking on duplicate entries
(refer to
this
and this):
typeset -U path
PATH pre-populated
The reason your path already has some entries in it is due to your system shell files setting path for you. This is covered in a couple other posts:
Why and where the $PATH env variable is set?
Where is the source of $PATH? I cannot find it in .zshrc
one liner, without opening ~/.zshrc file
echo -n 'export PATH=~/bin:$PATH' >> ~/.zshrc
or
echo -n 'export PATH=$HOME/bin:$PATH' >> ~/.zshrc
To see the effect, do source ~/.zshrc in the same tab or open a new tab
Added path to ~/.zshrc
sudo vi ~/.zshrc
add new path
export PATH="$PATH:[NEW_DIRECTORY]/bin"
Update ~/.zshrc
Save ~/.zshrc
source ~/.zshrc
Check PATH
echo $PATH
OPTION 1: Add this line to ~/.zshrc:
export "PATH=$HOME/pear/bin:$PATH"
After that you need to run source ~/.zshrc in order your changes to take affect OR close this window and open a new one
OPTION 2: execute it inside the terminal console to add this path only to the current terminal window session. When you close the window/session, it will be lost.
If you are on macOS (I'm on Monterey 12.3.1), you may have been pulling your hair like I did metaphorically. These instructions above all worked for me within the terminal session, but I could never get it to persist no matter what I did with export. Moreover, I couldn't find the .zshrc anywhere.
Turns out Apple does it differently. The file you need to edit is etc/paths. You can simply sudo nano /etc/paths and add your path in a new line. Then simply restart terminal and voila.
for me PATH=$PATH:/path/to/file/bin
then export PATH worked.
to check echo $PATH . other solutions are adding the path temporarily.
I'm on Monterey 12.4 and the only way I could change the path was using the helper function. Editing text files in nano did diddly squat
# append
path+=('/foo/bar/yourpath')
# export to sub-processes
export PATH
to verify your new directory has been added correctly, you can use
print -l $path
thanks to the fact that its type is known to be an array

Resources