285

I have a shell script which I want to run without using the "sh" or "bash" commands. For example:

Instead of: sh script.sh

I want to use: script.sh

How can I do this?

P.S. (i) I don't use shell script much and I tried reading about aliases, but I did not understand how to use them.

(ii) I also read about linking the script with another file in the PATH variables. I am using my university server and I don't have permissions to create a file in those locations.

Ionică Bizău
  • 109,027
  • 88
  • 289
  • 474
Rameez Hussain
  • 6,414
  • 10
  • 56
  • 85
  • 1
    The answers indicate how to make the script executable, but don't seem to cover how to make it accessible. For that, create yourself a bin directory - `$HOME/bin` - if you don't already have one, add it to your PATH (near the front). Put the scripts (and any other programs) you want to execute directly without specify the pathname in here, or symlinks in here to where the actual programs are. – Jonathan Leffler Jan 08 '12 at 18:28
  • 1
    After you follow the answer(s) below, to drop the ".sh" you can rename the file: `mv example.sh example` and then `example` should work on its own. – PJ Brunet Dec 13 '16 at 06:14

13 Answers13

475

Add a "shebang" at the top of your file:

#!/bin/bash

And make your file executable (chmod +x script.sh).

Finally, modify your path to add the directory where your script is located:

export PATH=$PATH:/appropriate/directory

(typically, you want $HOME/bin for storing your own scripts)

fge
  • 119,121
  • 33
  • 254
  • 329
  • Hey thanks for your reply. I tried that out. Now I can run it without the "sh" command. But I still have to prefix the command with "./" which I don't want to. :) – Rameez Hussain Jan 08 '12 at 18:26
  • 5
    See comments about the path. You need to put your script in a directory which you have to append to your PATH. – fge Jan 08 '12 at 18:33
  • 2
    it didn't work in my case. but `source script.sh` worked fine, or rather `source ` – MycrofD Mar 22 '17 at 14:28
  • 4
    `source ./my-cool-script` (or `. ./my-cool-script`) will pollute the current shell session with any variables defined in the script. Sourcing should not be used unless you want to explicitly modify the shell session by setting environment vars, changing the directory, etc. Really terrible bugs could result otherwise, as variables from one script execution, if done via sourcing, could affect another script execution. – Daniel Waltrip Jun 20 '17 at 19:18
  • 3
    If you are sure the script folder is in PATH, and it still does not work without `./`, then you may have a name collision. Try renaming. – dstandish Sep 03 '17 at 06:30
  • you'll still get a `command not found` error if you are in the script directory and not including `./` . simply change to a different directory, and as long as the script is in your $PATH variable, it will work. – AndrewD Feb 07 '18 at 22:51
  • Ran into the same issue, and it was a naming collision as [chorbs](https://stackoverflow.com/users/2761682/chorbs) advised. – RobertMcReed Dec 24 '18 at 02:19
  • use "alias demo = 'bash demo.sh'", then you don't have to write "./". Just simply write 'demo' and bang... – Jay Sojitra May 23 '19 at 11:45
  • If you're receiving command not found the problem is not name collision, it would execute the wrong script/binary if was so. You may be setting you're path wrongly. You can `cd` to where the script is and issue `PATH=$PATH:$PWD` it would work – geckos Jul 04 '19 at 02:59
  • Also you have to set the PATH on the same `bash` session that you're executing. If you open a new terminal or another bash, or type bash on the same session your PATH is gone. If your script is trying to be executed by another command you may need to export it with `export PATH` so commands that run on your bash receives the up to date PATH – geckos Jul 04 '19 at 03:01
  • what is the zsh shebang? How do I find the right path for zsh? –  Jul 19 '19 at 01:39
  • @Daniel `type zsh` wild print it if it's in your `PATH`. If you are already running `zsh`, you can also try `echo "$SHELL"` – tripleee Jul 31 '19 at 15:43
  • @tripleee thanks! not sure how I missed this reply... `which zsh` works too! –  Nov 18 '19 at 00:22
  • How can `chmod +x script.sh` be done via a shell script, so it doesn't have to be done manually for several files? –  Nov 18 '19 at 00:22
  • @Daniel Please post a new separate question instead. Nobody will see your comments down here except by accident, and you are drifting further and further off-topic. Also, I don't understand what you are asking. – tripleee Nov 18 '19 at 05:14
  • To clarify (which I don't think is off-topic): "And make your file executable (chmod +x script.sh)." How can that be done in a shell script, so that running that script, executes that command, just like if one was to type it in Terminal? –  Nov 19 '19 at 03:06
  • On my Android shell (which is LineageOS), the shell is /bin/sh, which I must use the `sh` command to run a shell script. `./` does not work. Of course it has the executable flag on and file starts with `#!/bin/sh`. – midnite May 06 '22 at 15:48
80

These are the prerequisites of directly using the script name:

  1. Add the shebang line (#!/bin/bash) at the very top.
  2. Use chmod u+x scriptname to make the script executable (where scriptname is the name of your script).
  3. Place the script under /usr/local/bin folder.
    • Note: I suggest placing it under /usr/local/bin because most likely that path will be already added to your PATH variable.
  4. Run the script using just its name, scriptname.

If you don't have access to /usr/local/bin then do the following:

  1. Create a folder in your home directory and call it bin.

  2. Do ls -lA on your home directory, to identify the start-up script your shell is using. It should be either .profile or .bashrc.

  3. Once you have identified the start up script, add the following line:

    PATH="$PATH:$HOME/bin"
    
  4. Once added, source your start-up script or log out and log back in.

    To source, put . followed by a space and then your start-up script name, e.g. . .profile or . .bashrc

  5. Run the script using just its name, scriptname.

tripleee
  • 175,061
  • 34
  • 275
  • 318
jaypal singh
  • 74,723
  • 23
  • 102
  • 147
  • I dont know what the problem with the system is. I created a new shell script named "hello" with just an "echo "hello" " in it. I changed its permissions and tried ./hello. It dosn't work. it says- – Rameez Hussain Jan 08 '12 at 19:42
  • What changes have you made to your start up scripts? – jaypal singh Jan 08 '12 at 19:50
  • i tried sourcing the start up scripts. it says i dont have permissions to do so. – Rameez Hussain Jan 08 '12 at 19:51
  • That doesn't look right. The start up scripts should be in your home directory. Make sure you are in your home directory when you source them. – jaypal singh Jan 08 '12 at 19:52
  • I dont seem to have permissions to do this. I checked the home folder. It has the .bashrc file. But if I try to source it it says "Permission denied" – Rameez Hussain Jan 08 '12 at 20:06
  • Can you update the permission of your .bashrc file? Try giving it a full permission for test purposes using `chmod 777 .bashrc` – jaypal singh Jan 08 '12 at 20:11
  • I tried that, and tried sourcing it. Says I can't use the "." command. Then I tried editing the .bashcr file itself and then running the shell script. Nothing happened. – Rameez Hussain Jan 08 '12 at 20:18
  • if you have updated the .bashrc file and have added ur script directory to your path then just log out and log back in. The bachrc file gets sourced everytime you log in. – jaypal singh Jan 08 '12 at 20:24
  • Your home directory might be mounted with the noexec option, which will prevent you from executing it the way that you want to. – jordanm Jan 09 '12 at 00:38
  • 1
    `myscripts` is unconventional and you spell it differently (singular vs plural) in different places. A more common arrangement is to call it `bin` just like the directories for system binaries. – tripleee Nov 18 '19 at 05:22
  • 1
    Don't use Bash-only syntax in `.profile`, which is shared with other shells. `export PATH=value` is not portable, and should instead be broken up into two statements. Except of course you can almost certainly simply remove the `export` because surely, this variable will already be `export`ed for you, so there is no need to do that again. – tripleee Aug 01 '20 at 08:20
  • @tripleee Re `myscript(s)`, I edited it, but rather than trying to fix the typo, I changed it to `bin`. – wjandrea Aug 29 '20 at 06:03
  • 1
    @wjandrea Good initiative. I removed the `export` too. – tripleee Aug 29 '20 at 07:25
  • what are we gonna do for windows? – Asim Imam Dec 09 '22 at 15:22
23

Just make sure it is executable, using chmod +x. By default, the current directory is not on your PATH, so you will need to execute it as ./script.sh - or otherwise reference it by a qualified path. Alternatively, if you truly need just script.sh, you would need to add it to your PATH. (You may not have access to modify the system path, but you can almost certainly modify the PATH of your own current environment.) This also assumes that your script starts with something like #!/bin/sh.

You could also still use an alias, which is not really related to shell scripting but just the shell, and is simple as:

alias script.sh='sh script.sh'

Which would allow you to use just simply script.sh (literally - this won't work for any other *.sh file) instead of sh script.sh.

ziesemer
  • 27,712
  • 8
  • 86
  • 94
  • Hey! Thanks for your reply. I tried using aliases earlier. But nothing happened. I placed it immediately after the "#!/usr/local/bin/bash" line. What do you think is wrong? – Rameez Hussain Jan 08 '12 at 18:28
  • 1
    An alias can't be defined within your script - it has to be declared as part of your current environment. So just run the `alias` command at the shell prompt, and then the alias will be available to run the command with. – ziesemer Jan 08 '12 at 18:39
22

In this example the file will be called myShell

First of all we will need to make this file we can just start off by typing the following:

sudo nano myShell

Notice we didn't put the .sh extension? That's because when we run it from the terminal we will only need to type myShell in order to run our command!

Now, in nano the top line MUST be #!/bin/bash then you may leave a new line before continuing.

For demonstration I will add a basic Hello World! response

So, I type the following:

echo Hello World!

After that my example should look like this:

#!/bin/bash
echo Hello World!

Now save the file and then run this command:

chmod +x myShell

Now we have made the file executable we can move it to /usr/bin/ by using the following command:

sudo cp myShell /usr/bin/

Congrats! Our command is now done! In the terminal we can type myShell and it should say Hello World!

tripleee
  • 175,061
  • 34
  • 275
  • 318
15

You have to enable the executable bit for the program.

chmod +x script.sh

Then you can use ./script.sh

You can add the folder to the PATH in your .bashrc file (located in your home directory). Add this line to the end of the file:

export PATH=$PATH:/your/folder/here
Uku Loskit
  • 40,868
  • 9
  • 92
  • 93
6

You can type sudo install (name of script) /usr/local/bin/(what you want to type to execute said script)

ex: sudo install quickcommit.sh /usr/local/bin/quickcommit enter password

now can run without .sh and in any directory

JoelWass
  • 575
  • 1
  • 5
  • 6
  • ... Provided you also previously made sure the file is readable and executable for everyone. `chmod a+x quickcommit.sh` – tripleee Aug 01 '20 at 08:23
1

Add . (current directory) to your PATH variable.
You can do this by editing your .profile file.
put following line in your .profile file
PATH=$PATH:.

Just make sure to add Shebang (#!/bin/bash) line at the starting of your script and make the script executable(using chmod +x <File Name>).

Arpit Tyagi
  • 173
  • 1
  • 10
  • 2
    **Don't do this.** There are good reasons to *not* have the current directory on your `PATH`. It makes it too easy - especially for beginners - to accidentally shadow crucial system commands, or worse, to be tricked into executing somebody else's commands. – tripleee Aug 01 '20 at 08:26
0

Here is my backup script that will give you the idea and the automation:

Server: Ubuntu 16.04 PHP: 7.0 Apache2, Mysql etc...

# Make Shell Backup Script - Bash Backup Script
    nano /home/user/bash/backupscript.sh
        #!/bin/bash
        # Backup All Start
        mkdir /home/user/backup/$(date +"%Y-%m-%d")
        sudo zip -ry /home/user/backup/$(date +"%Y-%m-%d")/etc_rest.zip /etc -x "*apache2*" -x "*php*" -x "*mysql*"
        sudo zip -ry /home/user/backup/$(date +"%Y-%m-%d")/etc_apache2.zip /etc/apache2
        sudo zip -ry /home/user/backup/$(date +"%Y-%m-%d")/etc_php.zip /etc/php
        sudo zip -ry /home/user/backup/$(date +"%Y-%m-%d")/etc_mysql.zip /etc/mysql
        sudo zip -ry /home/user/backup/$(date +"%Y-%m-%d")/var_www_rest.zip /var/www -x "*html*"
        sudo zip -ry /home/user/backup/$(date +"%Y-%m-%d")/var_www_html.zip /var/www/html
        sudo zip -ry /home/user/backup/$(date +"%Y-%m-%d")/home_user.zip /home/user -x "*backup*"
        # Backup All End
        echo "Backup Completed Successfully!"
        echo "Location: /home/user/backup/$(date +"%Y-%m-%d")"

    chmod +x /home/user/bash/backupscript.sh
    sudo ln -s /home/user/bash/backupscript.sh /usr/bin/backupscript

change /home/user to your user directory and type: backupscript anywhere on terminal to run the script! (assuming that /usr/bin is in your path)

Tarik
  • 4,270
  • 38
  • 35
0

Enter "#!/bin/sh" before script. Then save it as script.sh for example. copy it to $HOME/bin or $HOME/usr/bin
The directory can be different on different linux distros but they end with 'bin' and are in home directory cd $HOME/bin or $HOME/usr/bin
Type chmod 700 script.sh
And you can run it just by typing run.sh on terminal. If it not work, try chmod +x run.sh instead of chmod 700 run.sh

  • The parts of this answer that don't restate information from very old existing answers are confused. – tripleee Mar 31 '19 at 16:17
0

Make any file as executable


Let's say you have an executable file called migrate_linux_amd64 and you want to run this file as a command like "migrate"

  1. First test the executable file from the file location:
[oracle@localhost]$ ./migrate.linux-amd64 
Usage: migrate OPTIONS COMMAND [arg...]
       migrate [ -version | -help ]

Options:
  -source          Location of the migrations (driver://url)
  -path            Shorthand for -source=file://path 
  -database        Run migrations against this database (driver://url)
  -prefetch N      Number of migrations to load in advance before executing (default 10)
  -lock-timeout N  Allow N seconds to acquire database lock (default 15)
  -verbose         Print verbose logging
  -version         Print version
  -help            Print usage

Commands:
  goto V       Migrate to version V
  up [N]       Apply all or N up migrations
  down [N]     Apply all or N down migrations
  drop         Drop everyting inside database
  force V      Set version V but don't run migration (ignores dirty state)
  version      Print current migration version
  1. Make sure you have execute privileges on the file
    -rwxr-xr-x 1 oracle oinstall 7473971 May 18 2017 migrate.linux-amd64
    if not, run chmod +x migrate.linux-amd64

  2. Then copy your file to /usr/local/bin. This directory is owned by root, use sudo or switch to root and perform the following operation

sudo cp migrate.linux-amd64 /usr/local/bin
sudo chown oracle:oracle /user/local/bin/migrate.linux.amd64
  1. Then create a symbolic link like below
sudo ln /usr/local/bin/migrate.linux.amd64 /usr/local/bin/migrate
sudo chown oracle:oracle /usr/local/bin/migrate
  1. Finally add /usr/local/bin to your path or user profile
export PATH = $PATH:/usr/local/bin
  1. Then run the command as "migrate"
[oracle@localhost]$ migrate
Usage: migrate OPTIONS COMMAND [arg...]
       migrate [ -version | -help ]

Options:
  -source          Location of the migrations (driver://url)
  -path            Shorthand for -source=file://path 
  -database        Run migrations against this database (driver://url)
  -prefetch N      Number of migrations to load in advance before executing (default 10)
  -lock-timeout N  Allow N seconds to acquire database lock (default 15)
  -verbose         Print verbose logging
  -version         Print version
  -help            Print usage

Commands:
  goto V       Migrate to version V
  up [N]       Apply all or N up migrations
  down [N]     Apply all or N down migrations
  drop         Drop everyting inside database
  force V      Set version V but don't run migration (ignores dirty state)
  version      Print current migration version
David Buck
  • 3,752
  • 35
  • 31
  • 35
Guru
  • 1
0
  1. Make the script file as executable by using file's properties
  2. Create alias for the executable in ~/.bashrc. alias <alias namme> = <full script file path>'
  3. refresh the user session to apply it. source ~/.bashrc
gobi
  • 511
  • 5
  • 13
  • Adding an alias per-executable is not good practice. Aliases can't be run except from at an interactive shell (they can't be called from other scripts or invoked from non-shell applications). There's no reason to have an alias at all if you install the executable at a location in the PATH. – Charles Duffy Nov 01 '21 at 21:18
0

Just to add to what everyone suggested. Even with those solutions, the problem will persist if the user wants to execute the script as sudo

example: chmod a+x /tmp/myscript.sh sudo ln -s /tmp/myscript.sh /usr/local/bin/myscript

typing myscript would work but typing sudo myscript would return command not found.

As sudo you would have to still type sudo sh myscript or sudo bash myscript.

I can't think of a solution around this.

-1

Just:

/path/to/file/my_script.sh
DimiDak
  • 4,820
  • 2
  • 26
  • 32