Apple - Why do I need to put sh before running .sh files?

If you're running your script from the shell, you don't actually need the #!/bin/sh shebang as outlined in this this answer–every Unix-like system I've used, including OS X, will default to /bin/sh if no interpreter is specifically specified (though it's a good idea as non-shells won't know how to execute your script unless you give the shebang.)

You also don't need an .sh extension. You do need to set executable permissions, e.g.

$ chmod +x script.sh

(The $ is the shell prompt; I'm using it to illustrate commands you give to the interactive shell. Don't type it!)

However, I think what your confusion is is that you have created a script, e.g. script.sh, in the current directory, and are trying to execute it by simply typing script.sh. e.g.

$ cat >script.sh
echo hello, world
^D
$ chmod +x script.sh
$ script.sh
-bash: script.sh: command not found

(^D means control-D. You will find this notation in many writeups on using Unix.)

The fact that script.sh in this case is a shell script is only half the problem; your actual issue is that, by default, the shell will not search the current directory for a program. However, this works:

$ sh script.sh
hello, world

because sh is taking the script as an argument.

You can execute a script–or, again, any executable–in the current directory, if it is marked executable (i.e. chmod +x), by specifying that you want to run the one in the current directory:

$ ./script.sh
hello, world

You can also move the script to a directory on your PATH. I recommend /usr/local/bin for this if your script is intended to be used system-wide, or a bin directory in your home if the script is only for you. The latter requires you to add $HOME/bin, which expands to your new bin directory, to your PATH by adding the following lines to your .profile in your home directory:

PATH=$HOME/bin:$PATH
export PATH

Finally, you can, if you want, actually add the current directory to your PATH, which will allow you to just go to a directory containing script.sh–or any other executable–and type

$ script.sh

to execute it. However, I do not recommend this practice, as an attacker can now trick you into running an arbitrary executable by dropping an executable script (named, say, ls) into a directory you will be in. If you really want to do it, though, just add the following to your .profile:

PATH=.:$PATH
export PATH

You don't need to call sh if the script file is marked as executable. In that case, you can call it my name just like you would any other command from the existing shell.


To be fully proper, you'll want to do two things:

  1. Edit your script to include a shebang directive at the top of your script:

    #!/bin/sh

    ... That would tell the shell which interpreter to use to run the script; in this case, the /bin/sh executable.

  2. Mark the script as executable by you with the chmod command:

    chmod u+x scriptname.sh

Once you do both of those, you should be able to run your script by typing your script's file name on the command line. You'll need to be in the same directory as your script, unless you also take the added step of adding the containing folder to your PATH variable. If you don't care what shell runs the script, you don't need step one to specify sh but it's often better to be precise and set the "shebangsh".