zxに限らずだが、nodeでコマンドライン引数リストを参照するとき
コマンドライン引数をパースするライブラリを使っていない場合はprocess.argvからリストを取ってくる
zxでも単純にこれを使えばよいと思っていたが、zxのオプションを渡すとprocess.argvで渡ってくる順番が変わるのでそのまま使おうとすると当たり前だが挙動が変わってしまう
minimist
zxではminimistがデフォルトで含まれていて、最初からminimistでパースした引数のリストを参照できる(argv)
他のライブラリを使わない場合は、argvを最初から参照するのが良さそう
ただこれだけだとちょっと微妙で、次の2つのパターンのときにコマンドライン引数リストの内容が変わってしまう
- オプションなし、キーと値がセットのオプションを渡したとき
- eg) --shell=/bin/bash
- (true/false)で表せるようなオプションを渡しているとき
- eg) --quiet
argv._で取得できるコマンドライン引数のリストに自身のファイル名が含まれる場合と含まれない場合が出てくる
- sample.mjs
#!/usr/bin/env zx console.log(argv);
$ zx sample.mjs a b c
{ _: [ 'sample.mjs', 'a', 'b', 'c' ] }
$ zx --shell=/bin/bash sample.mjs a b c
{ _: [ 'sample.mjs', 'a', 'b', 'c' ], shell: '/bin/bash' }
$ zx --quiet sample.mjs a b c
{ _: [ 'a', 'b', 'c' ], quiet: 'sample.mjs' }
そこで、自身のファイル名がコマンドライン引数のリストに入っていても除外することで実行時のオプションによりコマンドライン引数リストの内容が変わってしまう現象を防ぐ
path
zxにはpathもデフォルトで含まれているので自身のファイル名をコマンドライン引数リストから除けば実行時のオプション内容によって影響を受けることはない
- sample.mjs
#!/usr/bin/env zx console.log(path.basename(__filename)); console.log(argv); console.log(argv._.filter(a => a !== path.basename(__filename)));
$ zx sample.mjs a b
sample.mjs
{ _: [ 'sample.mjs', 'a', 'b' ] }
[ 'a', 'b' ]
$ zx --quite sample.mjs a b
sample.mjs
{ _: [ 'a', 'b' ], quite: 'sample.mjs' }
[ 'a', 'b' ]
これでオプションなどによって挙動に影響を与えるということはなくなったはず
余談
挙動の変更
ちょっと別の話だが、物によっては実行時にオプションを渡さず、コードの中でコントロールできるものもある
--quiteなどのオプションであれば
$.verbose = falseとコード中に書くことで制御可能
他にもREADMEに色々書いてある