When writing some complicated scripts for processing, I prefer to use JS to traditional shell scripts because I am more familiar with JS. When it comes to file-related operations, a few shell commands are certainly more convenient, but Node’s own child_process is a bit less interesting and doesn’t feel very comfortable.

The ZX package, released earlier this year and recently updated with version 2.0, is essentially a wrap around the native Child_process, providing optimizations for operations such as parameter pass-through and some default behaviors. It’s also Promise based, so it can be used in asynchronous functions as much as you want.

As a regular NPM package, not to mention the installation section, Node is definitely needed and goes straight to the use section.

The basic use

Start by creating a runnable ZX script:

echo '#! /usr/bin/env zx \n console.log("Hello, zx")' >> script.mjs
chmod +x script.mjs
Copy the code

After specifying the runtime environment as ZX, we can run zX scripts directly like normal shell scripts.

Execute shell instructions

When a shell directive needs to be executed, it is wrapped with a $symbol and a template string, which internally uses the spawn of child_process and returns a value of type ProcessPromise .

For example, try to create a delete file and display the number of files in the directory:

await $`echo '' >> ~/abc`;
let count = parseInt(await $`ls -1 ~ | wc -l`);
console.log(`Files: ${count}`);
await $`rm ~/abc`;
count = parseInt(await $`ls -1 ~ | wc -l`);
console.log(`Files: ${count}`);
Copy the code

Or upload files concurrently in some recording script:

const HOST = '1.1.1.1:3000';
let files = ['a.mp4'.'b.mp4'];
let target = '/home/ubuntu/rsync';
await Promise.all(files.map((filename) = > $`rsync -azP ./${filename} ${HOST}:${target}`));
Copy the code

Zx also supports error handling:

try {
  await $`exit 1`;
} catch (p) {
  console.log(`Exit code: ${p.exitCode}`);
  console.log(`Error: ${p.stderr}`);
}
Copy the code

Built-in functions and tool libraries

In addition, zX also wraps some common commands and tool libraries for easy use:

// shell cd
cd('/tmp');

/ / the node - fetch the package
const res = await fetch('https://wttr.in');
if (res.ok) {
  console.log(await res.text());
}

/ / the readline package
const env = await question('Choose a env: ', {
  choices: Object.keys(process.env),
});

// setTimeout implements sleep
await sleep(1000);

// Color output chalk
console.log(chalk.blue('This is blue'));

// fs-extra
const content = await fs.readFile('package.json');
Copy the code

Additional Polyfill

Zx adds some additional polyfills to esM scripts for ease of use:

/ / __filename and __dirname
console.log(__filename, __dirname);
// require
const { version } = require('package.json');
Copy the code

reference

  • google/zx