Bash Cheatsheet

For inspiration, and some examples of how GeneSystem manifests might be useful see below for some commands and their usage in installation steps:

Backup an Existing File

Before you apply changes to a file (say by echo-ing something into it). It can be a good idea to make a backup of the file. This can also make it easy to restore the machine back to its previous state. Here’s an example step doing just that with the cp command:

{
  "name": "backup pre-existing zshrc",
  "exe": {
    "install": {
      "cmd":[
        "cp $HOME/.zshrc $HOME/zshrc.bak"
      ],
    },
  },
  "tags": "backup zshrc"
},

Check File System Before Running a Step

[ -d <path>] and [ -f <path>] can be used to check the existance of a directory and file respectively before running a command. If the directory or file exists, then the command returns a zero exit status, otherwise it returns a non zero status when they don’t exist.

This is useful for optionally running a step dependant on the state of the file system. See below for more specific examples and usage:

Checking for a Directory

To check for a directory before running a step:

{
  "name": "create folder if not exist",
  "exe": {
    "install": {
      "skip": "[ -d $HOME/Code ]",
      "cmd": [
        "mkdir -p $HOME/Code"
      ],
    },
  },
  "tags": "setup folders"
}

Checking for a File

To check for a file before running a step:

{
  "name": "greet user on first run",
  "exe": {
    "install": {
      "skip": "[ -f $HOME/Code/.greeted ]",
      "cmd": [
        "echo 'Welcome'",
        "touch $HOME/Code/.greeted"
      ],
    },
  },
  "tags": "setup folders"
}

Check Environment Before Running a Step

[[ -n $VAR ]] can be used to check for the presence of an environment variable before running a step. The following example adds GOENV_ROOT to a .zshrc file if it’s not detected in the environment.

{
  "name": "greet user on first run",
  "exe": {
    "install": {
      "skip": "[[ -n $GOENV_ROOT ]]",
      "cmd": [
        "echo 'export GOENV_ROOT=\"$HOME/.goenv\"' >> $HOME/.zshrc"
      ],
    },
  },
  "tags": "setup folders"
}

One thing to remember when checking for whether an environment variable has been set or not is the state of the terminal profile before the manifest installation or removal. For example, if a previous step set the environment variable, it might not be detectable from later steps even though they run in order. This is because the profile is not reloaded between commands. If this is the case, you might want to use grep instead to detect an environment variable setting.

Grep for Value

grep is very useful for detecting strings within files. If you know precisely a string or a partial string that when it exists in a file means the step should be skipped, this might be a good way to detect that:

{
  "name": "set nodenv init",
  "exe": {
    "install": {
      "skip": "grep 'eval \"$(nodenv init -)\"' $HOME/.zshrc",
      "cmd": [
        "echo 'eval \"$(nodenv init -)\"' >> $HOME/.zshrc"
      ],
    },
  },
  "tags": "set nodenv init"
},

Recursively Make Directory

It can be tedious to write steps or multiple commands to create parent directories. The mkdir -p command makes the step definition much more efficient:

{
  "name": "create application",
  "exe": {
    "install": {
      "skip": "[ -d $HOME/Code/andrewbigger/application ]",
      "cmd": [
        "mkdir -p $HOME/Code/andrewbigger/application"
      ],
    },
  },
  "tags": "setup folders"
}

Check Whether App or Library Installed

which is a good way to detect whether the setup should attempt to install a library. In the following example, brew is installed if it is not already:

{
  "name": "install homebrew",
  "exe": {
    "install": {
      "skip": "which brew",
      "cmd": [
        "/bin/bash -c \"$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)\""
      ],
    },
  },
  "tags": "install homebrew"
},