Shell scripting in macOS – Part 1

The scripts in the following articles are written in macOS Big Sur. You can use these concepts to create scripts on UNIX and Linux too.

This is the first part of a multipart series. You can find links to further articles at a table located at the bottom of this article. I will be updating this article with links to new articles as I publish them.

What is shell scripting?

Shell scripts are simply files that list out a series of commands in the sequence in which they are to be executed. By commands we typically mean other shell commands. But these could also be other executables, scripts, or commands from other languages.

Why do we need it?

There are several reasons. The most common reason being automation. For example, If there are steps that we perform on a repeated basis such as checking for the presence or absence of particular files we could easily automate this task with the help of a script. Or If we want to perform certain tasks at scale: such as creating a set of files and folders that should always be there within the user’s home folder.

Scripting also has the added benefit of consistency. By performing the tasks the same way we can ensure that our desired outcome is the same every time. 

What is required for creating shell scripts?

Before we go ahead and look at how to create our own scripts there are a few things we need to keep ready at hand.

  • First we would need to know the commands we would have to execute to achieve our goal. This list is quite large and one would not necessarily know all the commands supported. But overtime your knowledge of these commands will grow. So do not worry!
  • Second, We need to pick a shell interpreter.
  • We also need to decide how we will be accessing the command line interface. This would most likely be via the Terminal application, but there are other ways too.
  • Finally we need to decide on the editor we will use to create our scripts. I will talk about this a little later.

Shell interpreters

The shell interpreter is as the name says the object that will interpret the commands and execute them. The default shell interpreter for macOS is zsh starting macOS Catalina. We can choose to use that or any other interpreter. While most commands we will be using will be common ones that are available across all interpreters be aware that some commands may be unique to certain interpreters only.

Commands

We will need to know some basic commands that will help us compose our scripts.There are several commands available in macOS. We will be learning about quite a few of those over the course of the next few articles. The table below lists some of the commands that we will be using.

CommandDescription
cdChange directory. This command changes the current working directory to the specified path. We use this command to navigate to another folder.
mvThis command moves the contents from the specified folder to another folder.
lsLists the contents of the folder.
rmRemove the specified content.
cpCopy the contents of a folder to another folder.
touchUpdate the timestamp for a file or folder.
pwdPrint the complete path to the present working directory.
mkdirCreate a folder.
echoPrint the string out onto stdout.

Be aware that many commands will create/modify/delete items in the current folder if the absolute path is not specified in the command. This may result in unexpected or unintended behavior.

Editor

I will be using Xcode as the editor for our scripts. However, you can use any editor you wish. You will find the a list of editors at the bottom of the article.

Using Xcode as an editor for scripting may be a bit of an overkill. It is a very heavy application primarily designed for app development. If you are currently developing apps and are already using Xcode then you can go ahead and use it for scripting too. Otherwise it might be a good idea to go in for a different tool.

Building our first shell script

In order to build our script. Let us take a simple scenario. Let us suppose that every user in our organisation must have the following folders:

  • Tools
  • Reports
  • Help

All these folders must be located in the home folder for each user. So let us take it step by step. We will perform these commands manually from the Terminal application.

  1. The first command is the command to navigate to the home folder.
cd ~/

The ~/ represents the path to the current user’s home folder. The cd command is used to change the working directory to the newly specified path.

  1. Now we will create the 3 folders.
mkdir Tools
mkdir Reports
mkdir Help

All the 3 commands are creating a new folder. Since we did not specify the complete path to the folder. These items are created in the working directory.

  1. Now we will step into each folder and create an empty hidden file.
cd Tools
touch .ToolsFolderCreated
cd ..

Let us break down these commands one by one.

First we go into the Tools folder.

Then we use the touch command to update the timestamp of the.ToolsCreated file. Since the file doesn’t exist the touch command creates the file for us. Also as the file starts with the . character it is hidden by default. Creating a hidden file like this is a good way of leaving behind some flag indicating that the script ran successfully. Of course, in our example this can be determined simply by seeing the folders that are created. But in more elaborate situations they are a very useful way of laying down milestones for a script.

The next command takes us back a step outside the enclosing folder. In our case the Tools folder is inside the home folder. So we are going back to the home folder.

We will repeat the steps again for the Reports and Help folders.

cd Reports
touch .ReportsFolderCreated
cd ..

cd Help
touch .HelpFolderCreated
cd ..

Those are the commands we execute to get the desired result. You can switch to the graphical user interface to see if the items have been created. Note that the files created with the touch command will not be visible by default.


Now that we have seen how these commands work. Let us create a script.

  1. Use any editor you like. I will start off with TextEdit. Create a new file. If you are using TextEdit then do not forget to convert the formatting to plain text. Format > Make Plain Text.
  2. Give the file any name you want. I will call it folderCreator.zsh.
  3. Save the file where ever you wish. I will save it on the Desktop folder for now.
  4. On the first line we need to specify our interpreter. This indicates that the commands in our script need to be interpreted by the zsh interpreter.
#!/bin/zsh
  1. One the next line we will type the command to go to the home folder.
#!/bin/zsh

cd ~/
  1. Next we will type the command to create the 3 folders.
#! /bin/zsh

cd ~/

mkdir Tools
mkdir Reports
mkdir Help
  1. Finally we will add the code to create the hidden files.
#! /bin/zsh

cd ~/

mkdir Tools
mkdir Reports
mkdir Help

cd Tools
touch .ToolsFolderCreated
cd ..

cd Reports
touch .ReportsFolderCreated
cd ..

cd Help
touch .HelpFolderCreated
cd ..

  1. A nice addition to the script would be the echo command. This command would let the person who is running the script know about the different events taking place.
#! /bin/zsh

echo "Running script to create folders."

cd ~/

echo "Creating folders: Tools, Reports, Help"
mkdir Tools
mkdir Reports
mkdir Help

echo "Creating hidden file for Tools folder."
cd Tools
touch .ToolsFolderCreated
cd ..

echo "Creating hidden file for Reports folder."
cd Reports
touch .ReportsFolderCreated
cd ..

echo "Creating hidden file for Help folder."
cd Help
touch .HelpFolderCreated
cd ..

echo "Task completed. Have a nice day!"

Your completed script should look like:

#! /bin/zsh

echo "Running script to create folders."

cd ~/

echo "Creating folders: Tools, Reports, Help"
mkdir Tools
mkdir Reports
mkdir Help

echo "Creating hidden file for Tools folder."
cd Tools
touch .ToolsFolderCreated
cd ..

echo "Creating hidden file for Reports folder."
cd Reports
touch .ReportsFolderCreated
cd ..

echo "Creating hidden file for Help folder."
cd Help
touch .HelpFolderCreated
cd ..

echo "Task completed. Have a nice day!"
  1. Save the script.

That’s it. You have just created your first script.

Running our first shell script

The next step would be to run our script. There are 2 ways of doing this. We will look at both the options.

Option 1

We can directly run the script using the zsh command.

zsh ~/Desktop/folderCreator.zsh

Note that we will need to provide the path to the script file.

This is a straightforward way. We simply tell the interpreter to execute the commands in our script.

Option 2

This option requires a few more steps.

  1. First we need to change the permissions on the script. We need to make sure that all 3: Owner, Group, Everyone else have the read and execute permissions. Of course, you are free to change the permissions to whatever you want. But the execute capability is required. We will change the permissions from the command line.
chmod ugo+x ~/Desktop/folderCreator.zsh

There are other ways of writing this command too. But for now we are simply saying that we want to add the execute capability to the Owner, Group, Everyone else. If you look at the file in the GUI, you will see its icon has changed to the executable icon.

  1. Next we will simply run the following command from the terminal application.
./Desktop/folderCreator.zsh

Now we can simply run the script by invoking it from the terminal application. Or we can trigger it from the graphical user interface by simply double clicking on the file.

There you go. You have successfully created and tested your own script. Try to play around with some of the terminal commands and create your own scripts.

Video

You can watch the video I have created in case you wish to see the steps.

Download script

You can download this version of the script from here.

Popular editors for shell scripts

Here are some links for popular editors.

Coderunner

Emacs

Atom

Xcode

Shell scripting topics

Here are the links to more parts in this series. I will add the links as I publish the articles.

List of macOS Terminal commands

This article lists out different macOS terminal commands you might encounter. You can use this list as a starting point in your search for a command to perform a specific task. This list is by no means exhaustive.

Basic terminal commands are not listed here. Some of them are listed in the following Terminal command articles.
Terminal Commands – Basic
Terminal Commands – Part 2
Terminal Commands – Part 3

Many of the commands have also been used in the article I wrote some time back. You can have a look at the scripts to see some of the commands being used.

To get more information about the commands simply run the following command from within Terminal Application. For example, to view the manual page for tmutil simply type:

man tmutil

For fdesetup

man fdesetup
Here is a nice command to quickly open the man page in the Preview App.
man -t tmutil | open -f -a /System/Applications/Preview.app

Note

  • This is not a complete list of commands
  • Some commands are available through the macOS Recovery Volume only
  • Some commands required other resources such as the OS installer
  • Some commands are available with certain versions of the OS only

Please read the documentation for more details. Use the commands with care. Improper use of commands may result in loss of data or damage to the computer.

Commands


Installation

CommandDescription
startosinstallUsed to start the installation of macOS from the command line.
createinstallmediaUsed to create an external install disk.

Security

CommandDescription
fdesetupManage FileVault configuration.
securityManage keychain and security settings
spctlManage security assessment policy
csrutilConfigure System Integrity Protection (SIP) settings
resetpasswordPassword reset utility located in the Recovery Partition

File System

CommandDescription
hdiutilUsed to manipulate and manage disk images.
diskutilUsed to modify, verify, & repair local disks.

Data Management

CommandDescription
tmutilUsed to configure Time Machine settings in macOS
screencaptureTakes screenshot of the specified screen and saves the image at the specified location.
mdlsUsed to get metadata attributes for a given file
mdutilUsed to manage metadata stores that are used by Spotlight

Settings

CommandDescription
defaultsUsed to modify plist files. Typically used to update preference files.
ioregUsed to view the I/O kit registry
system_profilerUsed to generate system hardware & software reports.
plutilUsed to check syntax of property lists or covert property lists from one format to another
AssetCacheManagerUtilUsed to configure content caching settings.
openUsed to open documents from within the command line.
networksetupPerform network configuration.
systemsetupUsed to configure machine settings in System Preferences.
launchctlUsed to manage and inspect daemons, agents, & XPC Services

Applications

CommandDescription
codesignUsed to create, check, display code signatures.
pkgbuildUsed to build installer packages
productbuildBuilds a product archive
installerSystem software and package installer tool

User Account Management

CommandDescription
dsclThis is a command line Directory service utility that allows us to create, read, and manage Directory Service data.
sysadminctlUser account management
passwdChange user password
loginUsed to login to another user account.

Server & Device Management

CommandDescription
profilesUsed to install, remove, list, or manage Configuration profiles.
serveradminUsed to manage the services in macOS
mdmclientLocated in /usr/libexec/mdmclient it is used to manage interactions with the MDM.
asrApple Software restore: Used to copy volumes.

Scripting

CommandDescription
osascriptUsed to execute the given AppleScript

Share any commands you may know of in the comments window.

Disclaimer

The information Is Provided “As Is”, Without Warranty Of Any Kind, Express Or Implied, Including But Not Limited To The Warranties Of Merchantability, Fitness For A Particular Purpose And Noninfringement. In No Event Shall The Authors Or Copyright Holders Be Liable For Any Claim, Damages Or Other Liability, Whether In An Action Of Contract, Tort Or Otherwise, Arising From, Out Of Or In Connection With The information provided Or The Use Or Other Dealings In The information.

Useful scripts for macOS

Getting Started

You might find these articles useful

One of the advantages with scripts is the fact that you can easily automate many tasks. Here is an article that walks you through that process.

If you come across a situation where you want to perform a set of tasks on multiple computers then scripts come in very handy.

I will be providing the Shell Script version of the task. Feel free to make changes to the scripts as required. I will try to provide an AppleScript version of the tasks a little later.

This is not the only way to implement the scripts. There may be multiple approaches towards achieving the same result. You will have to explore and examine the correct approach.

This is not a comprehensive list. The scripts should give you some ideas and act as a useful reference when you are creating your own scripts.

I have tested these scripts on macOS Catalina 10.15

Download

You can download all the scripts from here.

Script CategoryPage Number
Settings and Accounts1
Security2
Data3
Information Collection4
File System5

Disclaimer

The Software Is Provided “As Is”, Without Warranty Of Any Kind, Express Or Implied, Including But Not Limited To The Warranties Of Merchantability, Fitness For A Particular Purpose And Noninfringement. In No Event Shall The Authors Or Copyright Holders Be Liable For Any Claim, Damages Or Other Liability, Whether In An Action Of Contract, Tort Or Otherwise, Arising From, Out Of Or In Connection With The Software Or The Use Or Other Dealings In The Software.


WARNING

Please try these scripts on a test computer. Some of the scripts do make changes to the system. Always test before using these scripts.

Automation on the Mac

Automating tasks on the Mac is very useful for a wide variety of reasons. In this article we are going to look at the different technologies available for automating tasks.

TOOLS

Automator

The simplest way of achieving automation. Automator which is a built in application allows you to create task workflows by simply dragging in a set of predefined routines into a specified sequence. Let us explore how it works by creating a watermarking print plugin

Let us look at how we can create a print plugin that automatically adds a watermark to the pdf file.

  1. First get hold of an image that you will use as a watermark.
  2. Open Automator.
  3. Click on “New Document”
  4. Choose Print Plugin as the type of task to createScreen Shot 2018-03-21 at 11.58.26 AM
  5. From the left hand side drag the “Watermark PDF Documents” option. You will be able to locate this from the PDF library on the extreme right.1
  6. Add the image that will be used as a watermark. Customise the settings to your desired level. You may have to use trial and error till you get the desired output.
  7. Similarly drag the Move finder Items to the right. You will be able to locate this from the Files & Folders library.2
  8. Save the task as WatermarkCreator.
  9. Open a text file.
  10. Select File > Print
  11. Click on the PDF drop down in the print dialog.3.4
  12. Select the newly created task.
    3
  13. You have now successfully setup your own watermark creator.

Shell Scripting

For those coming from a Linux/Unix background this might be a familiar option. Very often users need to run a series of terminal commands repeatedly. While it is not difficult to do this, wouldn’t it be nice if we could write all the commands in a single file? Shell Scripts help users do just that.

To create a shell script:

  1. Open TextEdit
  2. Write the following code in there (We will write code to create a series of files and folders in our home folder for a user called admin):
    #! /bin/sh
    cd /Users/admin/
    if [ -d "/Users/admin/Applications/" ]; then
    echo "Applications Folder Exists"
    else
    mkdir Applications
    fi
    if [ -d "/Users/admin/Sites/" ]; then
    echo "Sites Folder Exists"
    else
    mkdir Sites
    fi
    if [ -d "/Users/admin/Developer/" ]; then
    echo "Developer Folder Exists"
    else
    mkdir Developer
    fi
    cd Developer
    if [ -d "/Users/admin/Developer/iOSProjects/" ]; then
    echo "iOSProjects Folder Exists"
    else
    mkdir iOSProjects
    fi
    if [ -d "/Users/admin/Developer/macOSProjects/" ]; then
    echo "macOSProjects Folder Exists"
    else
    mkdir macOSProjects
    fi
    
  3. Save the file with the name FolderCreator on the Desktop.
  4. Open the Terminal Application
  5. Let us make the script executable. To do that, run the commands:
    cd ~/Desktop
    chmod 777 FolderCreator
    
  6. Now run the command:
    ./FolderCreator

You have now easily created your own shell script. For more information about terminal commands you can read the following articles: Terminal Commands for OS X – BasicTerminal Commands for OS X – Part 2Terminal Commands – Part 3, & Configuring/Troubleshooting OS X Using Command Line

AppleScript

AppleScript is Apple’s proprietary scripting technology. It comes bundled as a part of macOS. To create AppleScript tasks we need to use the built in AppleScript editor.

Here is an example of a small AppleScript

tell application “Finder” to set the view for all Finder Windows as column view
tell application “Finder” to close every Finder Window
tell application “Safari”
open location “<a href="http://www.arunpatwardhan.com">http://www.arunpatwardhan.com</a>
open location “<a href="http://www.amaranthine.in/feedback">http://www.amaranthine.in/feedback</a>
open location “<a href="http://www.amaranthine.in/gallery">http://www.amaranthine.in/gallery</a>
end tell

Copy that block of commands in your AppleScript editor and see what comes up.

There are many more things that can be done with AppleScript. You can have popup windows asking users for commands, turn off the computer. Change the settings for different parts of the OS and for different applications. All this with commands written in a single file. All the user has to do is double click the file.

For more information about AppleScript visit Apple’s Developer site.

Launch Agents, Launch Daemons

NOTE: Scheduling Launch Agents/Launch Daemons improperly may leave your computer in an unusable state. Always test this on a computer that does not contain important data. If you are unsure, please consult someone with knowledge of the same before proceeding ahead.

Launch Agents/Launch Daemons allow you to schedule tasks which are to be performed at intervals. You can also use them to ensure that tasks are kept running and that the user does not have the possibility to quit them. To setup a launch daemon:

  1. First create a Plist file that looks like the one below. I have created a script called echoer and placed it in the /Users/admin/Applications folder where admin is the user.Screen Shot 2018-03-22 at 10.34.18 AM
  2. Place the file in the ~/Library/LaunchAgents folder. Name it in.amaranthine.demod.plist
  3. Run the command in terminal to load the Launch Agent.
    launchctl load ~/Library/LaunchAgent/in.amaranthine.demod.plist

That’s it you have just setup a simple launch agent which will ensure that your script runs every 6 seconds.

For more information or to create detailed Launch Agents/Launch Daemons visit:Creating Launch Agents & Launch Daemons

Login Items

An easy way to automatically load, Applications/Files/Folder, as soon as well login is to use Login Items. This is very easy to do.

  1. Open System Preferences > Users & Groups
  2. Switch to the Login Items tab.IMG_1560
  3. Click on the ‘+’ sign at the bottom to add new Applications. Let’s add Maps so that it launches as soon as we login. You should see it appear in the list.IMG_1561

That’s it. You have setup login items. You can repeat this process for as many applications as you wish.

Others

PHP, Perl, Python, Javascript, Swift allow you to create custom automated tasks and routines. These require knowledge of programming.

Choosing the right approach

Which one to choose depends on a lot of factors but we can break it down to 2:

  • You are a technically qualified person and understand things like programming, scripting and command line
  • You are an end user working either at home or in office.

End User

If you are an End user then you should really stick to Automator and Login Items. These are the ones that are the easiest to implement and least likely to cause any issues. You could venture and explore other options if you have a good understanding of them. Or you can ask the IT or Tech Support teams to help you with scripting and other technologies.

Tech Support or IT Person

Any of the tools mentioned above can be used by you. Make sure that you have a good command over the tools and are able to troubleshoot issues arising out of their usage.

Note: The programs/applications/tools and languages mentioned in this article may not cover all the available options. Also, anyone who uses or implements the items mentioned in the article does so at their own risk. The author does not take responsibility for any loss or damage that may arise from the use of the programs/applications/tools and languages mentioned above.