Key point is this: Extensions are irrelevant in any Unix-like system system.A filename is just name and has no effect on whether or not script or compiled executable can run. A programmer may add a .sh
extension to designate that a file is shell script, or .py
for python script, but unlike Windows , any unix doesn't care about naming, it cares about permissions.
What matters is the executable permission granted to a file. Which you can check with
ls -l /path/to/file
Running executables
To run script there are generally several ways.
- If your current directory is the same as the script, and script has executable permissions you can run it like so
./my_script_name
. The .
means current directory.
- If your current directory is different and script has executable permissions, you can run it by specifying full path:
/home/user/bin/my_script_name
(The above two methods rely on having executable permission set ; whether or not file is part of $PATH
variable is irrelevant. Presence of #!
line also matters; without it, it the script will be executed by the current shell you have open. If I have csh
script without that line, and try to run it in bash with ./my_script.csh
, it will fail)
- If your script is located in directory that is part of your
$PATH
variable, you can run it just by calling the name. You can call chmod
command in command line just by typing its name because it's in /bin
folder. /bin
is always part of $PATH
variable. In this case executable permissions and location of the script matter
- Specifying an interpreter as command and script as argument. That way script will serve as input file to the interpreter.
- Sourcing a file. The
. filename.sh
or source filename.sh
will make the script be treated as if it was keyboard input, i.e. as if it was typed into command line directly. In this case executable permissions and location don't matter
Examples
Example #1 , running with interpreter, to exec permissions
$-> ls -l abc.py
-rw-rw-r-- 1 xieerqi xieerqi 44 Apr 27 22:39 abc.py
$-> python abc.py
a
b
c
Example #2, running with ./
executable permission set, shebang line set.
$-> cat abc.py
#!/usr/bin/env python
for letter in 'a' 'b' 'c' :
print letter
$-> ls -l abc.py
-rwxrwxr-x 1 xieerqi xieerqi 66 Apr 27 23:02 abc.py*
$-> ./abc.py
a
b
c
Example #3, running without shebang line set (fails, because bash can't read python scripts ; no shebang line assumes current shell as interpreter )
$-> cat abc.py
for letter in 'a' 'b' 'c' :
print letter
$-> ./abc.py
./abc.py: 2: ./abc.py: Syntax error: word unexpected (expecting "do")
Example #4 , running script that has executable permissions set form folder that is part of $PATH
variable
# /home/xieerqi/bin is part of my path variable
$-> echo $PATH
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/opt/microchip/xc16/v1.25/bin:/opt/microchip/xc32/v1.40/bin:/opt/microchip/xc8/v1.35/bin:/home/xieerqi/bin:/home/xieerqi/bin/sh
$-> # current directory is /home/xieerqi
$-> pwd
/home/xieerqi
$-> # move the file to ~/bin
$-> mv ~/abc.py ~/bin/abc.py
$-> # now I can run it just by calling the name
$-> abc.py
/home/xieerqi/bin/abc.py: 2: /home/xieerqi/bin/abc.py: Syntax error: word unexpected (expecting "do")
$-> # Syntax error because again, no interpreter specified.
$-> # must add #!/usr/bin/env python
$-> vi /home/xieerqi/bin/abc.py
$-> # after adding the line with vi text editor, we can run
$-> abc.py
a
b
c
Example #5, removing extension, still runs because extensions don't matter, but it has permissions and is part of $PATH
:
$-> mv ~/bin/abc.py ~/bin/abc
$-> abc
a
b
c
.sh
as an extension is in many circumstances considered bad practice: It's contrary to how other commands are named (you don't runls.elf
), it's often misleading (if yourfoo.sh
starts with#!/bin/bash
, then runningsh foo.sh
will run it with a different interpreter than it's built for), and if you rewritefoo.sh
to be a Python program, using that extension means you need to choose between keeping the now-misleading name and rewriting every program that calls it.+x
set -- wherefoo.sh
is a library that can be sourced into any POSIX shell,foo.bash
can be sourced into bash,foo.ksh
into ksh, etc.