As McLovin says, the automatically set, readonly
EUID) variable is a special feature of
bash (and some other shells). It's not standard for Bourne-style shells and
sh cannot be assumed to set these variables. In particular,
sh in Ubuntu is (currently, by default)
dash, which does not set them.
You have two options:
- Cause your script to be run by
bash instead of
- Change your script so it's more portable and doesn't require
Running Your Script With
You haven't told us the name of your script (which is okay). I'm going to call it
cleanup, as that's the name of the similar script in the guide you're working from.
Note in particular that I am not calling it something like
cleanup.sh. This is because I don't recommend you name it with a
.sh suffix suggests it is compatible with
- Most scripts aren't given a suffix at all, and having a
.bash suffix may even be interpreted as suggesting your file is a "library" rather than a "top level" script. That is, that it provides code to be sourced by other scripts (for example, with the
. builtin) rather than actually run directly.
However, including a
.sh suffix will not affect the technical behavior of your script in any way. There is no technical advantage or disadvantage associated with doing so.
Add a hashbang line as the very first line of your script:
Make your script executable with
chmod +x cleanup.
Now you can run your script by running the command:
./cleanup, when it's in the current directory. (Especially when scripting for education, exploration, testing, fun, or other limited or one-time use, this is perhaps the most common way.)
/path/to/cleanup, in general. If the first word of a command contains a
/ it is interpreted as path to an executable file. (That's the reason for the above
./ syntax, as
. means the current directory.)
By first word I mean the command up to but not including its first unescaped space or tab:
foo-bar/baz is the first word of
foo-bar/baz qux, while
spam\ ham is the first word of
spam\ ham eggs because the space before
ham is escaped with a backslash.
cleanup, if it's in a directory in your
PATH (and no directory listed first has an executable of the same name, and it is not superseded by a shell builtin, function, or alias).
Regardless of whether or not a script
cleanup has a
#!... hashbang line or what that line says:
sh cleanup will still (attempt to) run it with
sh as the interpreter.
bash cleanup will still (attempt to) run it with
bash as the interpreter.
This is because, in those cases, you are actually running the interpreter (
bash) and passing the name of the script to the interpreter, to be run. Many programs accept names of files to open on the command line, and shells like
bash follow this convention.
Making Your Script Portable
If you want to make your script portable, the simplest way is to not use
$UID at all, and instead use some facility available to all Bourne-style shells.
In general there's no built-in shell facility to determine user ID. But you can use
id. This is an external program rather than a shell builtin, but like
ls, it's reasonable to expect it will be present.
id by itself outputs a bunch of info, but
id -u gives just the effective user ID.
So instead of
if [ "$UID" != "$ROOT_UID" ], you can use:
if [ "$(id -u)" != "$ROOT_UID" ]
Technically, this is not equivalent.
bash gives the real user ID, and
id -u really corresponds to
$EUID. If you really want the UID and not the EUID, use