At some point in your career, it's likely you'll need to write scripts for the command line – there are cases where it makes sense to use vanilla bash scripting for this and that will usually work just fine for simple tasks like renaming things and deleting folders.
If you're anything like me though, it's much more enjoyable and productive to write these tools in a familiar language like Javascript, or even better – Typescript.
You get all the niceties of a modern language without any of the weird gotchas of bash and terminal syntax/behaviour.
In this article I'll cover a simple method for writing command line scripts in Typescript.
So! First things first. we need to create a directory where our scripts will live.
If you're on a mac or linux machine, I recommend creating a directory in your home
folder ~
simply called scripts
.
Within this folder we'll create a file called hello-world.ts
and globally install our 2 required dependencies (If you haven’t already, download and install node, but you probably knew that!)
1mkdir ~/scripts && cd ~/scripts
2npm i -g typescript ts-node
3tsc --init
4touch hello-world.ts
Learn about the handy npm shortcuts above
Note: If you know of a clean way to do this without globally installing ts-node and typescript, I'd love to hear about it!
Now we can place the following code in our hello-world.ts
file
1#!/bin/sh
2":" //#; exec /usr/bin/env ts-node -P ~/scripts/tsconfig.json "$0" "$@"
3
4console.log('Hello, World!');
Credit to Sam over at sambal.org for this clever shebang trick
Finally, we need to make this file executable with chmod
chmod +x hello-world.ts
And now we can run it!
1./hello-world.ts
2Hello, World!
Note: You may see an error from ts-node about an unrecognized option 'esModuleInterop' – if this happens to you, you can simply remove that line from ~/scripts/tsconfig.json
So far we've created our scripts directory where our scripts will live, installed the required dependencies to run them and set up a simple script to get us started.
Next we'll do some housekeeping to make our lives easier as our library of scripts grows over time.
One of the first things I do when I write a new script is create an alias to run it – I'll assume we're all running bash, but if you're using zsh or some other shell the steps here will be very similar.
First we'll edit our .bashrc to add an alias for our new script
1echo "alias hello_world='~/scripts/hello-world.ts'" >> ~/.bashrc
2source ~/.bashrc
Now we can run hello_world
from anywhere on our machine and get the same script!
1cd some/other/directory
2hello_world
3Hello, World!
More advanced scripts#
So we've created a simple script for outputting to the console, what if we want something a little more useful?
Let's create a script that prints out the 'scripts' portion of the package.json for whatever directory we're in. This can be useful if you're not sure what package scripts are available for any given project.
First we create our script file – I'll call it list-package-scripts.ts
Within list-package-scripts.ts
I'll add the following code:
1#!/bin/sh
2":" //#; exec /usr/bin/env ts-node -P ~/scripts/tsconfig.json "$0" "$@"
3
4import { readFile } from 'fs';
5
6readFile(`${process.cwd()}/package.json`, (err, data) => {
7 if (err) {
8 throw err;
9 }
10 const parsed = JSON.parse(data.toString('utf-8'));
11 console.log(parsed.scripts);
12});
Now we need to make this script executable!
chmod +x list-package-scripts.ts
now we can run this command in any node project and see what npm scripts are available to us:
1cd some/other/node/project
2~/scripts/list-package-scripts.ts
3# example output, will be different for every project!
4{ start: 'npm run watch',
5 'build:ts': 'tsc',
6 'watch:ts': 'tsc --watch',
7 watch: 'npm run clean && npm run build:ts & npm run watch:ts & gulp watch & wait',
8 test: 'gulp test' }
Hopefully this article provides a good jumping off point for your own scripts!
Please leave a comment or share the article if you found this useful – happy coding!