Google発のJavaScriptで書けるシェル  「zx」

Google発のJavaScriptで書けるシェル 「zx」

2021.05.11

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

Introduction

シェルを書きたいときにBashは手軽に使えるけど、
少し込み入ったスクリプトを書こうとするとちょっと面倒。
NodeいれてJavaScript書くのもいいけど、
いろいろセットアップが手間。
そんな人にピッタリはまるかもしれないのがzx
Google発、JavaScriptで記述できるシェルです。

Top Level await使ってシェルコマンドがそのまま使用可能です。
また、Promise.allでコマンド並列実行ができたりするので便利です。

Environment

  • OS : MacOS 10.15.7
  • Node : v14.16.1

Top Level awaitがサポートされたNode(v14.8)以降が必要ぽい?

Setup

では早速セットアップしてみます。
npmでzxをグローバルインストール。

			
			
% npm i -g zx

% zx
usage: zx <script>

		

Try

zxではスクリプトを .mjs拡張子にします。
(トップレベルawaitを使えるようにするので)
拡張子を.jsにしたい場合、void async function () {...}()とスクリプトをwrappします。

まずはscript.mjsファイルを作成し、Hello Worldしてみます。

			
			
#!/usr/bin/env zx
console.log("Hello zx!");

		

スクリプトの先頭にzxシェバンを記述。

実行権限を付与して、

			
			
% chmod +x ./script.mjs

		

zxで実行。

			
			
% zx ./script.mjs
Hello zx!

		

$Command でコマンド実行できます。
実際はchild_processのexec関数を使ってコマンドを実行して、
Promise を返しているとのこと。

			
			
let count = parseInt(await $`ls -1 | wc -l`)
console.log(`Files count: ${count}`);

		
			
			
% zx ./script.mjs

$ ls -1 | wc -l
       3
Files count: 3

		

Promise.allでコマンドの並列実行も簡単に書けます。

			
			
await Promise.all([
  $`sleep 1; echo 1`,
  $`sleep 2; echo 2`,
  $`sleep 3; echo 3`,
]);

		

node-fetchのwrapperでhttp通信。

			
			
let resp = await fetch('http://wttr.in')
if (resp.ok) {
  console.log(await resp.text())
}

		

readlineのwrapperで対話形式のシェルも楽に書ける。

			
			
let name = await question('What is your username? ')
let token = await question('Choose env variable: ', {
  choices: Object.keys(process.env)
})

console.log(`${name},${token}`);

		

urlを指定して、リモート先にあるスクリプトを実行することも可能。

			
			
% zx https://medv.io/example-script.mjs

		

Summary

Node(npm)は必要ですが、使い勝手のよさそうなシェル環境が容易に構築できるので
よさそうです。(ワンバイナリでほしいという意見もありますが)

References

この記事をシェアする

FacebookHatena blogX

関連記事