When I want to run .sh
files in Terminal, I need to put sh
in front of them.
Is there any way to avoid this, and thus save typing?
Ask Different is a question and answer site for power users of Apple hardware and software. It only takes a minute to sign up.
Sign up to join this communityWhen I want to run .sh
files in Terminal, I need to put sh
in front of them.
Is there any way to avoid this, and thus save typing?
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
sl
or lls
or l
... i.e., typos. Just leave .
out of $PATH
. Also, you may not (or should not) necessarily trust everyone on your system. For example, suppose there's some exploit that allows an attacker to drop an arbitrary file into some directory, but they need you to execute that file in order to escalate to a better exploit (e.g., collect data and phone home). Defense in depth!
/tmp
or some other world-writable directory.
/tmp
et al. come with the territory.
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:
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.
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".
/bin/sh
, though they don't hurt.
ksh
scripts back in my days on HP-UX -- but it's good to know that it isn't strictly necessary.
Sep 7, 2013 at 19:16
exec
syscall, you get ENOEXEC
(exec format error). Sorry about that, @bmike, @ChrisW.Rea. I'm going to go edit my answer now.