Menu

Node.js process.argvでコマンドライン引数を受け取る

process.argvは、プログラムを起動したコマンドラインの配列です。nodeの実行ファイル、スクリプトのパス、続いて入力した引数がすべて入っています。自分の引数だけならprocess.argv.slice(2)を使います。

このページのコードはエディタで実行できます。編集してすぐに結果を確認できます。

process.argv は、Node.jsのプログラムを起動したコマンドラインを入れた配列です。インデックス0は node 実行ファイルのパス、インデックス1はスクリプトのパスで、自分の引数はインデックス2から始まります。つまり process.argv.slice(2) で、ユーザーがファイル名の後に入力したものがそのまま手に入ります。値は常に文字列です。

最初の2つはフルパスなので、ここでは最後の部分(node と index.js)だけを表示し、続いて [ 'Ada', '42', '--verbose' ] を表示しています。引数の欄を Grace 7 に変えて実行し直すと、配列もそれに合わせて変わります。

process.argvに入るもの

シェルは node 以降の行をスペースで分割し、その断片をNode.jsに渡します。ファイル名より前に書いたフラグは、あなたのプログラムではなくNode.js自身のものです。

node --max-old-space-size=4096 index.js --port=8080
# process.argv.slice(2) is [ '--port=8080' ]
# process.execArgv is      [ '--max-old-space-size=4096' ]

クォートで囲むと複数の単語が1つの引数にまとまり("Ada Lovelace" は1つの文字列として届きます)、*.txt のようなパターンはNode.jsに届く前にシェルがファイル名へ展開します。

slice(2)で引数を取り出す

たいていのスクリプトは、期待する引数を分割代入で受け取り、それぞれにデフォルト値を与えます。

Hello, Ada が表示されました。引数1つが name に入り、greeting はデフォルト値になりました。引数の欄で Ada の後に Hi を足すと Hi, Ada と表示され、欄を空にすると Hello, world になります。

数値は文字列として届く

シェルには型がありません。引数はすべて文字列なので、変換するまでは計算がおかしくなります。

a + b は文字列をつないで 75 になり、Number() を使うと 12 になりました。数値でない単語は NaN になるので、Number.isNaN で確認し、壊れた値のまま進まずに使い方のメッセージを表示しましょう。

--name=valueフラグを手でパースする

フラグが2つ3つなら、短いループで十分です。このループは --port=8080 を port: '8080' に、値のない --verbose を true に変え、それ以外は位置引数として残します。

{"port":"8080","verbose":true} と [ 'build', 'src' ] が表示され、port は文字列のままです。このループは -p のような短いフラグや、次の引数に書かれた値(--port 8080)には対応していません。それが必要なら、次に紹介する組み込みのパーサーを使います。

組み込みのパーサー、util.parseArgs

Node.js 18.3以降には util.parseArgs があり、長いフラグと短いフラグ、次の引数に書かれた値、真偽値、デフォルト値を扱えます。

const { parseArgs } = require('node:util');

// node index.js -p 8080 --verbose src
const { values, positionals } = parseArgs({
    options: {
        port: { type: 'string', short: 'p', default: '3000' },
        verbose: { type: 'boolean', short: 'v' },
    },
    allowPositionals: true,
});

console.log(values);      // [Object: null prototype] { port: '8080', verbose: true }
console.log(positionals); // [ 'src' ]

parseArgs はデフォルトで process.argv.slice(2) を読みます。宣言していないオプションがあると例外を投げるので、--prot のようなタイプミスに気づけます。未知のフラグを受け付けたいなら strict: false を渡します。オプションの型は string と boolean だけなので、数値にはやはり Number() が必要です。values はプロトタイプを持たないオブジェクトなので [Object: null prototype] と表示されますが、普通のオブジェクトと同じように読めます。

よくある間違い

process.argv[0] を最初の引数だと思って読む。 それは node のパスです。最初の引数は process.argv[2] です。

すべてが文字列だということを忘れる。 '10' > '9' は false です。文字列は1文字ずつ比較されるからです。先に変換しましょう。

引数に秘密情報を入れる。 コマンドラインはシェルの履歴や、マシン上のほかのユーザーも見られるプロセス一覧に残ります。パスワードやAPIキーは代わりに環境変数で渡してください。

よくある質問

npmスクリプトに引数を渡すには?

-- の後に書きます。npm run start -- --port=4000 のようにすると、npmは -- より後ろをすべてスクリプトに渡し、それが process.argv.slice(2) に現れます。

process.argv[2]がundefinedになるのはなぜですか?

その引数なしでプログラムを起動したからです。デフォルト値を与える(process.argv[2] ?? 'guest')か、使い方を表示して process.exit(1) で終了しましょう。

process.argvの代わりにyargsやcommanderを使うべきですか?

フラグが数個のスクリプトなら、組み込みの util.parseArgs で十分です。commanderやyargsのようなパッケージはヘルプ表示、サブコマンド、バリデーションを追加してくれるので、ツールにコマンドが複数あるなら元が取れます。

Coddyのプログラミング言語のイラスト

Coddyでコードを学ぼう

始める