Google製のJavaScript Shellラッパー”zx”を触ってみたYO!
はじめに
Twitter で少し前に盛り上がっていた、 google/zx という NPM ライブラリに触れてました。
新しいツールを触る機会は家の手伝いや子守をしていてここ数年全く取れていなかったのですが、今日はたまたま時間が作れました。
検証環境
$ uname -moi
x86_64 MacBookPro16,1 Darwin
$ bash -version | head -n 1
GNU bash, version 5.1.8(1)-release (x86_64-apple-darwin20.3.0)
$ node --version
v15.12.0
$ yarn --version
1.22.10
ツールの紹介
Bash は偉大だけと、多くのケースでスクリプトを書こうとするともっと高級な言語が選択されます。
文法や型に制約が強いほうがチーム開発には向いていますよね。
ちょっとした処理を Bash で書こうものなら、他のエンジニアから風当たりが強いです 。
JavaScript も良い選択肢ですが、JavaScript から Bash コマンドを呼び出す手間が面倒です。
そんな手間を違和感なく解決してくれるのが zx
とのことです。
インストール
npm と yarn のそれぞれの方法を紹介していますが、どちらにしてもグローバルインストールすることが推奨されているようです。
npm の場合
npm i -g zx
yarn の場合
僕はこちらでインストールしました。
yarn global add zx
使い方
ファイルの拡張子
.mjs
という拡張子のファイルを作成し、そこにスクリプトを記述してい来ます。
拡張を元に await
がトップレベルで利用できるようになります。( async な無名関数でくるんだりが不要 )
もちろん .js
という通常の JavaScript ファイルの拡張子でも zx
を使うことはできますが、この場合は void async function () { ... }()
でくるんでやる必要があります。
ファイルの SheBang ( シバン )
ファイルの一行目について。
Bash だと
#!/usr/bin/env bash
などと記述するあれですが、 .mjs
ファイルでは
#!/usr/bin/env zx
と書きておきます。
サンプルプログラム
カレントディレクトリのファイル数をカウントし、標準出力するスクリプトがサンプルプログラムとして掲載されていました。
早速作成してみます。
$ touch ./script.mjs
$ chmod +x ./script.mjs
$ vi ./script.mjs
コードを記述していきます。 ( $`...`
の部分に好きなシェルコマンドを記述できるようです。実行結果が文字列で返ってくると。これは面白い。 )
#!/usr/bin/env zx
let count = parseInt(await $`ls -1 | wc -l`);
console.log(`Files count: ${count}`);
作成したら実行してみます。
$ ls -1 | wc -l
2
Files count: 2
あ、そういう感じなんですね。$`...`
で実行した結果をスクリプト内で文字列として取得する前に、標準出力に流れちゃうんですね。
実行コマンドは標準出力に出力させない
$`...`
で実行したコマンドは標準出力に流さないようにするには、$.verbose
という変数の値を変更します。
#!/usr/bin/env zx
$.verbose = false;
let count = parseInt(await $`ls -1 | wc -l`);
console.log(`Files count: ${count}`);
実行してみます。
Files count: 2
$`...`
のコマンドとその実行結果が出力されなくなりました。
提供されている関数、変数
cd()
関数
カレントディレクトリを変更する関数です。
$`...`
の中で移動してもいいと思いますが、次の $`...`
では引き継がれません。
#!/usr/bin/env zx
await $`pwd; ls -1 | head -n 5`;
console.log("---");
// 移動してみる
await $`cd /etc; pwd; ls -1 | head -n 5`;
console.log("---");
// せっかく移動してもカレントディレクトリは元のディレクトリに戻っている
await $`pwd; ls -1 | head -n 5`;
console.log("---");
// cd() 関数を実行
cd("/etc");
console.log("---");
await $`pwd; ls -1 | head -n 5`;
console.log("---");
await $`pwd; ls -1 | head -n 5`;
実行します。
$ ./script.mjs
$ pwd; ls -1 | head -n 5
/tmp/work
script.mjs
---
$ cd /etc; pwd; ls -1 | head -n 5
/etc
afpovertcp.cfg
aliases
aliases.db
apache2
asl
---
$ pwd; ls -1 | head -n 5
/tmp/work
script.mjs
---
$ cd /etc
---
$ pwd; ls -1 | head -n 5
/private/etc
afpovertcp.cfg
aliases
aliases.db
apache2
asl
---
$ pwd; ls -1 | head -n 5
/private/etc
afpovertcp.cfg
aliases
aliases.db
apache2
fetch()
関数
node-fetch
で提供される fetch()
関数が使えます。
#!/usr/bin/env zx
let resp = await fetch("http://wttr.in");
if (resp.ok) {
console.log(await resp.text());
}
実行します。
$ ./script.mjs
いきなりカラフルな天気予報が出てきてびっくりしました。大阪。
sleep()
関数
setTimeout
関数のラッパー。
シンプルなインタラクティブコマンドラインインターフェースを提供できます。
#!/usr/bin/env zx
await $`date`;
await sleep(5000);
await $`date`;
実行。
$ ./script.mjs
$ date
金 5 14 22:18:38 JST 2021
$ date
金 5 14 22:18:43 JST 2021
全部 await
をつけないといけないのは少し面倒くさい。
chalk
パッケージ
chalk パッケージを明示的に import しなくても利用できます。
#!/usr/bin/env zx
console.log(chalk.blue("Hello world!"));
console.log(chalk.yellow.underline("Hello world!"));
console.log(chalk.green.italic("Hello world!"));
console.log(chalk.red.bold("Hello world!"));
実行。
$ ./script.mjs
カラフル。見やすい。
fs
パッケージ
fs パッケージを import なしで使える、ということですがあんまり旨味を感じません。
let content = await $`cat FILE.txt`;
で十分満たせているためです。
os
パッケージ
こちらもなくていいかな。OS 情報、シェルコマンドで取得できるので。
$.shell
変数に代入して、デフォルトシェルを変更できます。
$.shell = "/usr/local/bin/zsh";
$.prefix
Bash シェルスクリプトの最初のおまじない、 set
を設定するための変数です。
デフォルト値はすでに以下のようになっているとのことです。
$.prefix = "set -euo pipefail;";
ですので
- エラー発生時に中断する
- 定義されていない変数を参照したらエラー
- パイプラインのいずれかでエラーが発生したらエラー扱い
が $`...`
実行時のデフォルトの挙動となっているようです。
これは納得 。
$.verbose
$`...`
実行時のコマンドと実行結果が標準出力されるかどうかの設定。
デフォルトは true
とのことです。
個人的にはデフォルトは false
にしてほしかった。
リモートスクリプトの実行
Web 上に転がっているスクリプトを実行することもできるそうです。
$ zx https://medv.io/example-script.mjs
ただし、URL は https である必要があります 。
ひとこと
便利そうではありますが、使わない気もします。
ただ、Bash シェルスクリプトだと計算処理が貧弱なんですよね。
それから JSON データを操作したりする場合も便利そうな気はしますが、 jq
使えたらいいかなと思わないことも無いです。
chalk で色んな色、太字、斜体、アンダーラインなどの文字が出力できるのはコマンドラインインターフェイス作るのに良さそうな気もしますが、 zx
を各実行環境にインストールしてもらう必要があるがめ、配布に煩わしさを伴います。
ディスカッション
コメント一覧
まだ、コメントがありません