How to Run a Shell Script on a Unix Console or MAC Terminal

How to run a shell script on a Unix console or Mac terminal?

To run a non-executable sh script, use:

sh myscript

To run a non-executable bash script, use:

bash myscript

To start an executable (which is any file with executable permission); you just specify it by its path:

/foo/bar
/bin/bar
./bar

To make a script executable, give it the necessary permission:

chmod +x bar
./bar

When a file is executable, the kernel is responsible for figuring out how to execte it. For non-binaries, this is done by looking at the first line of the file. It should contain a hashbang:

#! /usr/bin/env bash

The hashbang tells the kernel what program to run (in this case the command /usr/bin/env is ran with the argument bash). Then, the script is passed to the program (as second argument) along with all the arguments you gave the script as subsequent arguments.

That means every script that is executable should have a hashbang. If it doesn't, you're not telling the kernel what it is, and therefore the kernel doesn't know what program to use to interprete it. It could be bash, perl, python, sh, or something else. (In reality, the kernel will often use the user's default shell to interprete the file, which is very dangerous because it might not be the right interpreter at all or it might be able to parse some of it but with subtle behavioural differences such as is the case between sh and bash).

A note on /usr/bin/env

Most commonly, you'll see hash bangs like so:

#!/bin/bash

The result is that the kernel will run the program /bin/bash to interpret the script. Unfortunately, bash is not always shipped by default, and it is not always available in /bin. While on Linux machines it usually is, there are a range of other POSIX machines where bash ships in various locations, such as /usr/xpg/bin/bash or /usr/local/bin/bash.

To write a portable bash script, we can therefore not rely on hard-coding the location of the bash program. POSIX already has a mechanism for dealing with that: PATH. The idea is that you install your programs in one of the directories that are in PATH and the system should be able to find your program when you want to run it by name.

Sadly, you cannot just do this:

#!bash

The kernel won't (some might) do a PATH search for you. There is a program that can do a PATH search for you, though, it's called env. Luckily, nearly all systems have an env program installed in /usr/bin. So we start env using a hardcoded path, which then does a PATH search for bash and runs it so that it can interpret your script:

#!/usr/bin/env bash

This approach has one downside: According to POSIX, the hashbang can have one argument. In this case, we use bash as the argument to the env program. That means we have no space left to pass arguments to bash. So there's no way to convert something like #!/bin/bash -exu to this scheme. You'll have to put set -exu after the hashbang instead.

This approach also has another advantage: Some systems may ship with a /bin/bash, but the user may not like it, may find it's buggy or outdated, and may have installed his own bash somewhere else. This is often the case on OS X (Macs) where Apple ships an outdated /bin/bash and users install an up-to-date /usr/local/bin/bash using something like Homebrew. When you use the env approach which does a PATH search, you take the user's preference into account and use his preferred bash over the one his system shipped with.

Execute bash and sh file on Mac without writing extension

Two problems...

Firstly, file is already an executable program in /usr/bin that tells you the type of a file - i.e. whether it is an image, or a song or a database. Quick example:

file a.png
a.png: PNG image data, 1 x 1, 1-bit colormap, non-interlaced

So, file is a bad name for a shell script - likewise is test.

Secondly, if you want to execute a script or program in your current directory, also known as dot (.), you either need to have dot in your PATH, or you need to explicitly tell your shell that the file you want to run is in the current directory. The easier option is the second, which means if your script is called fred, you run it with

./fred

which tells the shell it is in your current directory.

The longer option, if you want to always be able to run scripts in the current directory, is to add dot to your PATH. So, you locate your login script (probably $HOME/.profile) and you find the line that sets your PATH and you add the current directory to it.

export PATH=$PATH:.

Once you have set that, you are best off logging out and back in to have it take effect.

Some folks disapprove of the idea of adding dot to their PATH - I don't. YMMV.

How to run shell script daily in Mac Os X?

Yes of course, you can use crontab!

Firstly open the terminal, then launch crontab with:

crontab -e

In some cases you need to specify the editor (es.nano) like this:

env EDITOR=nano crontab -e

Now you can add your daily script at 3am like this:

0  3  *  *  *  sh /path/to/your/file

The format is:

min  hour  day_of_month  month  day_of_week  your_command

After save the cron, you can check the crontab list whit:

crontab -l

And if you want remove it with:

crontab -r

How to run a shell script in OS X by double-clicking?

  • First in terminal make the script executable by typing the following command:

      chmod a+x yourscriptname
  • Then, in Finder, right-click your file and select "Open with" and then "Other...".

  • Here you select the application you want the file to execute into, in this case it would be Terminal. To be able to select terminal you need to switch from "Recommended Applications" to "All Applications". (The Terminal.app application can be found in the Utilities folder)

  • NOTE that unless you don't want to associate all files with this extension to be run in terminal you should not have "Always Open With" checked.

  • After clicking OK you should be able to execute you script by simply double-clicking it.

Open new terminal in MacOSX and run node script

One way to do this would be to place the commands you want to run in a shell script with the .command extension. By default, these files will be opened in the Terminal application on macOS. This is a bit of a workaround, but I think it achieves what you would like to do.

Say we have the file hello.js containing the following:

console.log("Hello World")

And the shell script run_node.command

#!/bin/bash
node hello.js

Running the command open run_node.command will open a new Terminal.app instance and run the shell script, which in turn runs the node command. The terminal will close when the script exits.



Related Topics



Leave a reply



Submit