5

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

Community
  • 1
  • 1
jozxyqk
  • 16,424
  • 12
  • 91
  • 180

1 Answers1

9

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.

Hans Klünder
  • 2,176
  • 12
  • 8
  • 1
    Much cleaner. Thanks :). The function `source_it` will still be defined, but it's still better than hundreds of little variables hanging around. I could always `unset -f source_it`, which is only one thing. – jozxyqk Jan 05 '15 at 10:47
  • Just added a possible solution for this - but I don't know if this is guaranteed to work forever. Works fine for now, though. – Hans Klünder Jan 05 '15 at 10:58
  • Oh nice. Could also [`unset -f $FUNCNAME`](http://stackoverflow.com/q/1835943/1888983) anywhere inside the function. – jozxyqk Jan 05 '15 at 11:02