Google発のJavaScriptで書けるシェル 「zx」
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)は必要ですが、使い勝手のよさそうなシェル環境が容易に構築できるので
よさそうです。(ワンバイナリでほしいという意見もありますが)