Olivier D is almost correct, but you must set POSIXLY_CORRECT=1
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.
This does not address aliases though, so you must use \unset
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.)
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
You may be able to do what you want by piping awk
's output into a while read
loop. For example:
awk '/^#/ {next}; NF == 0 {next}; NF != 4 {exit 1} ; {print}' |
while read NAME METHOD URL TAG ; do
: # do stuff with $NAME, $METHOD, $URL, $TAG
echo "$NAME:$METHOD:$URL:$TAG"
done
if [ "$PIPESTATUS" -eq 1 ] ; then
: # do something to handle awk's exit code
fi
Tested with:
$ cat input.txt
# comment
NAME METHOD URL TAG
a b c d
1 2 3 4
x y z
a b c d
$ ./testawk.sh <input.txt
NAME:METHOD:URL:TAG
a:b:c:d
1:2:3:4
Note that it correctly exits on the fifth x y z
input line.
Best Answer
From the Upstart cookbook, Changing the Default Shell. There are 3 options, the first 2 involve changing your default shell from
/bin/sh
to something else. But the 3rd option looks like it would solve your particular issue.excerpt