What is the difference between ./ and sh to run a script?
Solution 1:
When you run any script by passing the filename to the script interpreter program, you are running the interpreter program with the script as an argument passed into it. For example this would look like the process 'sh' with the argument 'filename.sh'. The sh
interpreter is opening the file.
On the other hand if you run the script itself, the system calls out to the interpreter program specified and feeds in the scripts contents. In this case the process looks like 'filename.sh' with no arguments.
You should make sure you have a bang line:
#!/bin/bash
# bash script here
A bang line is the very first line in the script and starts with the same two characters #!
, these are what the system reads when it tries to execute the script and then the system passes the the script to the program immediately after. Note that this line isn't anything to do with bash and works just as well for python and perl, even though they're very different languages. You would use #!/usr/bin/python
for example and then follow it with python code.
Once you have your script, make sure you have set execute permissions:
chmod a+x filename.sh
Then you can run the script as its own process:
./filename.sh
Or put the file into a known location with a nice program name, like /usr/sbin
and run from anywhere:
sudo cp filename.sh /usr/sbin/program-name
program-name
And this is really the practical benefit of using the bang line with the right permissions - it's all about deployment. It's very hard to get users to run a script if they have to remember what program to run the script with. Remember to give a full path to the script every time they want to run it. Where as putting it in /usr/local/bin
for example, and making it executable, can save an awful lot of grief for people trying to use your script. These programs then become available to all users on the your computer.
It's also good for identification. If you go into the top
program, a script run without the bang line will just have the name of the interpreter i.e. bash
, perl
or python
. But if a script is run with the right permissions, then the name of the script shows.
Note: If you want to distribute a script that's accessible to everyone, then please create a man page and a deb package to install it. We need to reduce the number of random scripts online and increase the number of debs which can be uninstalled.
Solution 2:
The short version:
sh
is the command-line interpreter (dash).
Runningsh my_script
makes dash interpret the script../
tries to find out which interpreter to use, by looking at the first line. E.g.#!/bin/bash
, or even#!/bin/ruby
(as opposed to runningruby my_script
).
Solution 3:
The difference you do is,
with
sh
, you're running a program that will interpret the lines in your script just as it you would have typed them on the interactive prompt of the terminal,with
./
you're making a shortcut assuming that the script is just right here in the current directory you're sitting in AND it will be executable (because for instance you issuedchmod +x myscript.sh
), saving you invaluable time for future times :-)
Solution 4:
There are three main reasons you might be getting an error:
- the file is not executable
runchmod +x <myscriptname.sh>
to fix that - the partition does not allow running scripts (is mounted "
noexec
")
copy the script to/usr/local/bin
- the
#!
line has an error
make sure the first line is#!/bin/sh
or#!/bin/bash
If your first line looks right, but still isn't working, make sure the file doesn't have DOS line endings.
The error would look something like this:
$ ./myscript.sh
bash: ./myscript.sh: /bin/bash^M: bad interpreter: No such file or directory
You can fix it by running dos2unix <myscriptname.sh>
, or if you don't have that,perl -p -i -e 's/\r\n$/\n/' <myscriptname.sh>
.