# Bash script automation in macOS

# Introduction 
There are many scenarios in which bash scripts can be used to automate processes. Sometimes, I like to test things in Python. For instance, sometimes one of my colleagues asks me if something is possible in Python or how it is done. In those cases, I don't want to create a new project, but rather to create a new folder, throw a bunch of python files in, and figure out things. After some time, these test projects make a big mess in my directories, which I don't like.

To fix this, I made a bash script to remove all the files and folders that I have created under "temp" every time I boot my Mac. This blog post will describe how I managed to use macOS `launchd` to schedule a bash script to delete all the test files and folders.

# What is `launchd`?
As a Linux user or at least someone who has worked with Linux, you may be familiar with `systemd`. `launchd` is exactly the same, but it can do more like a job scheduler (corn replacement) and it is much more reliable than `systemd`.

## 1. How to interface `launchd`?
Anyhow, to interact with Launchd, use `launchctl` in your bash shell. Same as the `systemd` and the `systemctl` commands, isn't it? You can see more information about `launchctl` by typing `man launchctl` in your terminal window.

## 2. What `launchd` configuration files look like?
Having learned about the concept of `launchd` and its interface `launchctl`, it is now time to understand how we can define a new configuration for this. In contrast to `systemd`, which uses TOML config files, `launchd` makes use of `plist` files to define a configuration. Below is an example:

```plist
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>Label</key>
    <string>com.example.hello</string>
    <key>ProgramArguments</key>
    <array>
        <string>hello</string>
        <string>world</string>
    </array>
    <key>KeepAlive</key>
    <true/>
</dict>
</plist>
``` 

## 3. Where to save `launchd` configuration files?

There are three locations in which you can store a `launchd` configuration file. If your application is supposed to run as a daemon service, you can store it under `/System/Library/LaunchDaemons/`. If your application is supposed to run whenever a user logs in, you should store it under `/Library/LaunchAgents`. Finally, If your application is supposed to run whenever a specific user logged in it must be stored under `~/Library/LaunchAgents`.

# Creating the automation
It's time to set up the automation now that we know how `launchd` works. Let's create the bash script file first:

```bash 
rm -rf $HOME/projects/temp && mkdir $HOME/projects/temp
```

You need to save this script to `~/.scripts/loginscript.sh`. The script will delete the files and folders in the `temp` folder every time you run it. We will now need to create the config file for Launchd so the script runs every time we log in.

```plist
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>Label</key>
    <string>com.user.loginscript</string>
    <key>ProgramArguments</key>
    <array>
        <string>/bin/zsh</string>
        <string>PATH-TO-HOME-DIRECTORY/.scripts/loginscript.sh</string>
    </array>
    <key>RunAtLoad</key>
    <true/>
</dict>
</plist>

```

Let's save this to `~/Library/LaunchAgents/com.user.loginscript.plist`. Before registering it to `launchd` we first need to get the user id as it needs by `launchd`:

```bash
id -u
```
Copy the output and run the command below to register the configuration to `launchd`:

```bash
sudo launchctl bootstrap gui/<USER-ID> ~/Library/LaunchAgents/com.user.loginscript.plist  
```

# References 
- [Apple Documentions for Launchd](https://developer.apple.com/library/archive/documentation/MacOSX/Conceptual/BPSystemStartup/Chapters/CreatingLaunchdJobs.html)
