Olivier D is almost correct, but you must set POSIXLY_CORRECT
before running unset
. POSIX has a notion of Special Built-ins, and bash supports this. unset
is one such builtin. Search for SPECIAL_BUILTIN
in builtins/*.c
in the bash source for a list, it includes set
, unset
, export
, eval
and source
.
$ unset() { echo muahaha-unset; }
$ unset unset
muahaha-unset
$ POSIXLY_CORRECT=1
$ unset unset
The rogue unset
has now been removed from the environment, if you unset command
, type
, builtin
then you should be able to proceed, but unset POSIXLY_CORRECT
if you are relying on non-POSIX behaviour or advanced bash features later.
This does not address aliases though, so you must use \unset
(or use some form of quoting/escaping on that word) to be sure it works in interactive shell (or always, in case expand_aliases
is in effect).
For the paranoid, this should fix everything, I think:
POSIXLY_CORRECT=1
\unset -f help read unset
\unset POSIXLY_CORRECT
re='^([a-z:.\[]+):' # =~ is troublesome to escape
while \read cmd; do
[[ "$cmd" =~ $re ]] && \unset -f ${BASH_REMATCH[1]};
done < <( \help -s "*" )
(while
, do
, done
and [[
are reserved words and don't need precautions. You can't use =
in an alias or function name, so no precautions needed for setting POSIXLY_CORRECT
.)
Note we are using unset -f
to be sure to unset functions, although variables and functions share the same namespace it's possible for both to exist simultaneously (thanks to Etan Reisner) in which case unset-ing twice would also do the trick. You can mark a function readonly, bash does not prevent you unsetting a readonly function up to and including bash-4.2, bash-4.3 does prevent you but it still honours the special builtins when POSIXLY_CORRECT
is set.
A readonly POSIXLY_CORRECT
is not a real problem, this is not a boolean or flag its presence enables POSIX mode, so if it exists as a readonly you can rely on POSIX features, even if the value is empty or 0. You'll simply need to unset problematic functions a different way than above, perhaps with some cut-and-paste:
\help -s "*" | while IFS=": " read cmd junk; do echo \\unset -f $cmd; done
(and ignore any errors) or engage in some other scriptobatics.
Other notes:
function
is a reserved word, it can be aliased but not overridden with a function. (Aliasing function
is mildly troublesome because \function
is not acceptable as a way of bypassing it)
[[
, ]]
are reserved words, they can be aliased (which will be ignored) but not overridden with a function (though functions can be so named)
((
is not a valid name for a function, nor an alias
Thanks to commenters below for the extra suggestions.
env
command before, like this:env -i <SCRIPT.sh>
– Arkadiusz Drabczyk Mar 05 '15 at 12:58env
isn't redefined as a function as well. This is terrifying. I first thought that special characters would help -- calling with full path that includes/
, using.
to source, and so on. But those can also be used for function names! You can redefine any function you want, but it's hard to get back to calling the original command. – orion Mar 05 '15 at 13:03#/bin/sh
if this is not default interactive shell. – Arkadiusz Drabczyk Mar 05 '15 at 13:07