This series is an excerpt from the first chapter of my upcoming book “Scripting macOS” which will teach you to use and create shell scripts on macOS.
- Part 1: First Script
- Part 2: The Script File
- Part 3: The Code
- Part 4: Running the Script
- Part 5: Lists of Commands
- Part 6: Turning it off and on again
I will publish one part every week over the summer. Enjoy!
The Script File
In the previous part, we created a text file and named it
hello.sh. As we have mentioned before, all shell script files are text files.
The file extension
.sh is entirely optional. When you rename the file to merely
hello it will remain a functional script:
> mv hello.sh hello > ./hello Hello, World!
When you use the script frequently as a command line tool, typing the additional
.sh is cumbersome and does not ‘fit in’ very well with all the other command line tools. It is very common to remove the file extension in these cases.
.sh file extension tells Finder and other applications what kind of file this is. You can assign the
.sh file extension to be opened in your favored text editor when you double-click the file in Finder.
To do this, rename the file so it has the extension again:
> mv hello hello.sh
Then select the script file in Finder and open its Info panel (⌘I).
In the ‘General’ section of the info panel, you can see that Finder recognizes this file extension as a shell script.
In the ‘Open with’ section you can tell Finder which application to use to open this file. The popup list will show all applications you have installed that can open
.sh files. Select your favorite text editor.
To tell the system to open all files with a
.sh extension with your favorite text editor, click on the ‘Change All…’ button here. This will set your favorite text editor as the default application for the
.sh file extension.
- macOS User Guide: Choose an app to open a file on Mac
Some people like to use
.zsh file extensions to further distinguish scripts written specifically in bash or zsh. While this can be useful in some workflows—especially when translating scripts from bash to zsh—it is generally not necessary. The
.sh file extension works well for all these scripts. The
.zsh file extensions are also not automatically recognized by the Finder or text editors as shell scripts.
Aside from the actual script code, a shell script requires one more thing that distinguishes it from any other text file. You have to the tell the system that this file can be executed as a command.
This information is stored in the executable bit of the file privileges or file mode. You can see this information with the long form of the
> ls -l hello.sh -rwxr-xr-x@ 1 armin staff hello.sh
The file mode is displayed in the first ten characters in this output:
The leading dash designates this item as a file. (A directory will show
d, a symbolic link will show
The file access privileges are shown next. There are three sets of three flags or bits. The first three (in this case
rwx) are the privileges for the file’s owner. The second set (
r-x) are the privileges for group access and the last set (also
r-x) shows the privileges for all other user on this system.
The three flags in each set are
x, in that order. They stand for read (
r), write (
w) and execute (
x) and show the actions the users associated with each set can perform.
The file’s owner can read, write (or change), and execute (or run) this file. Users who are a member of the staff group, can read and execute this file, as well as every other user on this system.
Most documents and files merely contain text and data. The execute bit is not required. When you create a new file, the executable flag is disabled by default:
> touch newfile.txt > ls -l newfile.txt -rw-r--r-- 1 armin staff newfile.txt
Having the execute bit disabled by default is a sensible security measure. You will have to explicitly enable it when building scripts or other executables.
When you are writing shell scripts, you eventually want to execute them. To do this you have to enable the execute bit. When then execute bit is unset, you cannot run the script from the command line.
To demonstrate this—and to gain some familiarity with the command line tools required to manipulate the file mode—disable the executable bit of our
> chmod -x hello.sh
You can verify that the executable bit has been removed with the
ls -l command:
> ls -l hello.sh -rw-r--r--@ 1 armin staff 45 Feb 17 14:36 hello.sh
When you now attempt to run the command, it will fail and the shell will tell you the reason: you do not have the right permissions. Without the executable script, your shell script is merely a text file.
> ./hello.sh zsh: permission denied: ./hello.sh
You can re-set the executable bit with
> chmod +x hello.sh
You do not need write (w) permissions to execute a script, but you require read (r) permissions.
You can remove the executable privilege for group and/or other users for security. Since most Macs are used as single user systems this is not really relevant here. When you create, install, and run shell scripts on shared servers with other Unix or unix-like servers with many users, the proper access privileges may be extremely important. Please consult with the system administrator.
You will usually have to remember to set the executable bit when you create a new script. Some text editors may set it for you when they recognize you are working on a shell script.
Note: The executable bit has a different meaning for directories than it does for files. You can find the details in the
chmodman page or in my book ‘macOS Terminal and Shell‘