forwarding arguments with shell scripts

2021-01-03

 | 

~2 min read

 | 

289 words

When developing scripts to use to manage a project, I often find myself in a situation where I have multiple scripts that are mostly the same except for one or two differences.

For example, take the situation where I want a script to be able to see if there are any issues with my formatting and a second to fix those issues (if they exist). I might have the following in a package.json file

package.json
{
  "scripts": {
    "check": "prettier --ignore-path .gitignore --list-different \"**/*.+(js|json|css)\"",
    "format": "prettier --ignore-path .gitignore --write \"**/*.+(js|json|css)\""
  }
}

These scripts are nearly identical. Both specify which files to ignore (anything mentioned in the .gitignore) and which files to include (all files in the project that are .js, .json, or .css). In fact, there’s only one - the --list-different flag versus --write.

A solution to this problem is using a common script and then specifying the differences.

package.json
{
  "scripts": {
    "prettier": "prettier --ignore-path .gitignore \"**/*.+(js|json|css)\"",
    "check": "npm run prettier -- --list-different",
    "format": "npm run prettier -- --write"
  }
}

Similar to writing better tests, this approach clearly identifies what is different by not burying key values.

One of the things to note, however is how we forward along the remaining arguments, the --. When we run npm run check from the command line now, the shell will begin by figuring out what the prettier script is. Then it will see the -- which says to forward along all remaining arguments (in the case of the check script, this is --list-different) to that script.

Using this approach we’re able to stitch together scripts in a much more flexible way and bring clarity to what we’re actually trying to invoke without repeating ourselves multiple times.



Hi there and thanks for reading! My name's Stephen. I live in Chicago with my wife, Kate, and dog, Finn. Want more? See about and get in touch!