I am writing a function in ./bashrc to switch environment variables, commands, etc. This function is supposed to set up the necessary variables then call itself. Instead I get

bash: ./bash: No such file or directory

The function in my .bashrc script is this following:

switch() {
    EXISTS="$(ls ~/br/*$1 2> /dev/null)"
    if [ -z "EXISTS" ]; then
        export PS1="...."
        # Find "export BRANCH=" in .bashrc and replace it with input
        sed -i "0,/export/BRANCH=/{s/export BRANCH=.*$/export BRANCH\"$1\"/}" ~/.bashrc


I saw this post, Recursive call script, but I'm not sure the issue is the same.


My goal is to basically change environment variables, aliases, etc. So in my bash script I would originally have things such as:

export WORKNAME="br-190"
export WORKSPACE="~/workspace-${WORKNAME}"

alias sw='cd $BRANCH/source'
alias fix='mv ~/.good-files $WORKSPACE'

switch() {
   ... See Above ...

The goal is to change WORKNAME on the command line, such as

switch br-104

  • You should not edit .bashrc within .bashrc, you will most likely break it. Instead edit your question and tell us what you final goal is. I'm sure it can be achieved without editing .bashrc in itself.
    – chaos
    May 10, 2019 at 13:32
  • Chaos is very correct. This feels both dangerous and wrong. Why not do this in another file and source that instead?
    – terdon
    May 10, 2019 at 13:36
  • .bashrc is sourced not called. I don't see a recursive call in setup(). If I understand your goal, I think the final line in the else clause should be something like . ~/.bashrc or source ~/.bashrc which would source into the current environment .bashrc. However, my instinct says this should be avoided, or at the very least, done with great care. May 10, 2019 at 15:07

2 Answers 2


The first, obvious issue is this:

if [ -z "EXISTS" ]; then

That will always be true since you are checking whether the string EXISTS is empty. Since it's a string, it will never be empty. You want to do this instead:

if [ -z "$EXISTS" ]; then

Also, it is bad practice to use ls for this sort of thing and it is bad practice to use CAPS for script variable names. Only use capitals for environment variables so you can be sue there will be no name overlaps.

The next major issue is that you are calling ./$0. $0 is bash so ./$0 is ./bash which doesn't exist. What you want to do, presumably, is re-read .bashrc.

Then, of course, your sed command (even after correcting the syntax error) will always match itself. You need to make sure that you skip the line with the actual sed command, for example by only matching at the beginning of the line (also note the corrections):

sed -i "/^export BRANCH=/{s/export BRANCH=.*$/export BRANCH="$1\"/}" ~/.bashrc

But you can simplify to:

sed -i "s/^export BRANCH=.*$/export BRANCH="$1\"/" ~/.bashrc

Putting this together, you probably want something like:

switch() {
  shopt -s nullglob
  if [ -z "$exists" ]; then
    ## Are you sure you want the * there? That will expand to all
    ## files and directories beginning with $1
    export PS1="...."
    # Find "export BRANCH"a"
    sed -i "s/export BRANCH=.*$/export BRANCH=\"$1\"/" ~/.bashrc
    . ~/.bashrc
  • Thanks for the detailed answer. I do have EXISTS as $EXISTS, typo. As far as sed I only want the first occurance of export BRANCH= which is why I have the {0, , which is what I want but I don't see how the sed line will ever match itself, but thanks for the ^ reminder. Will give it a go. May 10, 2019 at 14:29
  • @jiveturkey ah, you're right. I think I just removed the 0, by mistake when I copied your function to play with it.
    – terdon
    May 10, 2019 at 14:41
  • The reason I expand, (~/br/*"$1") is, the $1 is expected to be the name of WORKNAME but in the ~/br/ directory it is pre-pended with the user, i.e. bob issues the command switch br-201 but the directory contains ~/br/bob-br-201 May 10, 2019 at 14:46
  • When using the shopt -s nullglob line, exists is ALWAYS empty. May 10, 2019 at 14:52
  • @jiveturkey OK, but if there are more than 1 files matching that glob, you might get unexpected consequences. I really can't help feeling this isn't the best approach here and would urge you to post a new question explaining what you are trying to do to see if anyone can come up with a better way.
    – terdon
    May 10, 2019 at 14:58

When .bashrc is being sourced, the running command is simply called bash.

Which in turn means the ./$0 expands to


And because bash is not a file in the current directory, you get that error message. You don't want to execute it, you want to source it, therefore there must be a space between . and the filename. Otherwise, . references the current working directory.

. ~/.bashrc
  • Didn't seem to work May 10, 2019 at 14:07
  • This comment is sure gonna help me figure out what the problem is...
    – Panki
    May 10, 2019 at 14:21
  • @jiveturkey when you say something "didn't work", you're not giving us any useful information. How did it fail? Did it do nothing? Did it do something but not what you wanted? What? Were there error messages? How did you try it? If you don't give us such details, a simple "didn't work" is not at all informative.
    – terdon
    May 10, 2019 at 14:26
  • Yeah, thanks, I was just being lazy. It gave me the exact error as last time. Thanks for the explanation of the error, make sense. But even when sourcing(re-reading) it, gives no different result.(i.e. same error message) May 10, 2019 at 14:36

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .