Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I stop variables in .bashrc being visible in the shell after sourcing?

Tags:

scope

bash

As an example, my .bashrc sources other scripts using a relative path in the following way, although my question is about any temporary variable used in .bashrc.

DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )
source $DIR/.somefile

Now I have DIR cluttering every shell. Short of explicitly unset DIR at the end of .bashrc, is there any way to limit the variable's scope?

[EDIT] To see a list: ( set -o posix ; set ) | less

like image 954
jozxyqk Avatar asked Jan 05 '15 10:01

jozxyqk


1 Answers

I appreciate very much that you ask that question. I hate variables that are no longer used but remain cluttering the shell. Some people build large bash scripts that do complicated things, and they don't care about such variables, and at the end there are hundreds of unused variables cluttering the namespace of the shell, and it's completely unclear which of them is still needed and which is not.

The general solution is to use local variables inside a function:

function source_it()
{
  local DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )
  source $DIR/.somefile
}

source_it

The variable DIR will be visible within the function and in all functions called by the function. It will cease to exist upon return from the function.

That will work even if you already have a global variable called DIR. The local variable will shadow the global variable DIR, thus the function uses the local version only, and once the function returns, the global version of DIR will be visible again, completely untouched.

Nested function calls can create arbitrary many versions of a local variable:

#!/bin/bash

factorial()
{
   local n="$1"
   if test $n -eq 0
   then
      echo 1
   else
      local m=$((n-1))
      echo $((n*$(factorial $m)))
   fi
}

factorial 5  # result: 120

Answering to your 1st comment: You can even write a self-destructing function. Try this:

#!/bin/bash

fun()
{
   echo this is fun
   # unset -f fun # upon your 2nd comment, changed that to:
   unset -f $FUNCNAME 
}

fun
fun

result:

this is fun
(script name): line 10: fun: command not found

However, that looks a bit strange - I am not sure if every future implementation of bash will allow functions to destroy themself as their last act.

like image 107
Hans Klünder Avatar answered Sep 25 '22 16:09

Hans Klünder