Reputation: 34247
I have a web server written in Node.js and I would like to launch with a specific folder. I'm not sure how to access arguments in JavaScript. I'm running node like this:
$ node server.js folder
here server.js
is my server code. Node.js help says this is possible:
$ node -h
Usage: node [options] script.js [arguments]
How would I access those arguments in JavaScript? Somehow I was not able to find this information on the web.
Upvotes: 3114
Views: 1903722
Reputation: 2324
Pass Arguments: When running a Node.js script, pass arguments after the script name. For example:
node app.js arg1 arg2 --key=value
Access Arguments: Node.js provides a process.argv array to access command-line arguments.
The first element (process.argv[0]) is the path to the Node.js executable. The second element (process.argv[1]) is the path to the script file. Subsequent elements (process.argv[2] and beyond) are the additional arguments.
Upvotes: 0
Reputation: 6568
Nodejs team added util.parseArgs
function in versions 18.3.0 and 16.17.0. So if you use these or higher versions of nodejs you can parse command line arguments with this native solution. parseArgs
was experimental up to v18 and is stable from v20.
An example of usage from the documentation:
const {parseArgs} = require('node:util');
const args = process.argv;
const options = {
foo: {
type: 'boolean',
short: 'f'
},
bar: {
type: 'string'
}
};
const {
values,
positionals
} = parseArgs({ args, options, allowPositionals: true });
console.log(values);
console.log(positionals);
Output sample:
$ node parseargs.js -f --bar b
[Object: null prototype] { foo: true, bar: 'b' }
[
'/Users/mbelsky/.nvm/versions/node/v18.12.1/bin/node',
'/Users/mbelsky/parseargs.js'
]
Upvotes: 29
Reputation: 4217
const getArgs = () =>
process.argv.reduce((args, arg) => {
// long arg
if (arg.slice(0, 2) === "--") {
const longArg = arg.split("=");
const longArgFlag = longArg[0].slice(2);
const longArgValue = longArg.length > 1 ? longArg[1] : true;
args[longArgFlag] = longArgValue;
}
// flags
else if (arg[0] === "-") {
const flags = arg.slice(1).split("");
flags.forEach((flag) => {
args[flag] = true;
});
}
return args;
}, {});
const args = getArgs();
console.log(args);
input
node test.js -D --name=Hello
output
{ D: true, name: 'Hello' }
input
node config/build.js -lHRs --ip=$HOST --port=$PORT --env=dev
output
{
l: true,
H: true,
R: true,
s: true,
ip: '127.0.0.1',
port: '8080',
env: 'dev'
}
Upvotes: 142
Reputation: 9422
const process = require( 'process' );
const argv = key => {
// Return true if the key exists and a value is undefined
if ( process.argv.includes( `--${ key }` ) ) return true;
const value = process.argv.find( element => element.startsWith( `--${ key }=` ) );
// Return null if the key does not exist and a value is undefined
if ( !value ) return null;
return value.replace( `--${ key }=` , '' );
}
Output:
node app.js
then argv('foo')
will return null
node app.js --foo
then argv('foo')
will return true
node app.js --foo=
then argv('foo')
will return ''
node app.js --foo=bar
then argv('foo')
will return 'bar'
Upvotes: 58
Reputation: 3820
Typescript way to do it with minimist.
npm i minimist @types/minimist
app.ts
// import
import { MyProgram } from './main';
// libraries
import minimist from 'minimist';
// interfaces
import { ParsedArgs } from 'minimist';
// code
const args: ParsedArgs = minimist(process.argv.slice(2));
let app = new MyProgram(args.a).getApp();
export { app };
Command to run after compiling to JavaScript with gulp
node app.js -a MyParam
Upvotes: 0
Reputation: 1141
Solution using Set to solve the position issue if using simple args (without key+values).
For example both commands will return same result:
node server.js detail json
node server.js json detail
const args = new Set(process.argv.slice(2));
Then one can use args.has('detail')
or args.has('json')
without worrying about position.
Upvotes: 9
Reputation: 53
You can use Rest operator to accept n numbers of arguments in a function and use it like this i have posted a sample program i hope which will help you to get the point.
function sum(...theArgs) {
let total = 0;
for (const arg of theArgs) {
total += arg;
}
return total;
}
console.log(sum(1, 2, 3));
// Expected output: 6
console.log(sum(1, 2, 3, 4));
// Expected output: 10
enter code here
Upvotes: -1
Reputation: 20730
const args = process.argv;
console.log(args);
This returns:
$ node server.js one two=three four
['node', '/home/server.js', 'one', 'two=three', 'four']
Minimist: For minimal argument parsing.
Commander.js: Most adopted module for argument parsing.
Meow: Lighter alternative to Commander.js
Yargs: More sophisticated argument parsing (heavy).
Vorpal.js: Mature / interactive command-line applications with argument parsing.
Upvotes: 445
Reputation: 61
Use the minimist npm package. it is the easiest method and don't need to worry about anything.
const arguments = require("minimist")(process.argv.slice(2));
// get the extra argument of command line .
eg node app.js --process="sendEmailWithReminder"
We can use it in windows task scheduler too.
Upvotes: 2
Reputation: 390
In the node code require the built in process lib.
const {argv} = require('process')
Run the program with their arguments.
$ node process-args.js one two=three four
argv is the array that follows:
argv[0] = /usr/bin/node
argv[1] = /home/user/process-args.js
argv[2] = one
argv[3] = two=three
argv[4] = four
Upvotes: 16
Reputation: 463
NodeJS exposes a global variable called process
.
we can use:
process.argv
to get the command line arguments passes to our script.
The output of process.argv
will be a list in the following order:
[
full-path-to-node-executable,
full-path-to-the-script-file
...additonal-arguments-we-provide
]
Upvotes: 4
Reputation: 383
The original question was asking to pass command line arguments, not about more complex parsing of arguments. Yet with all the complex answers, they all missed one simple, useful variation.
Did you know that the Unix shell supports named arguments? This dates back to the original Bourne shell in the 1980s. Usage is simple:
$ FOO=one BAR=two nodejs myscript.js
To fetch the parameters in Javascript:
var foo = process.env.FOO;
var bar = process.env.BAR;
Named parameters are much easier to read, once you get past two or three parameters. Optional parameters are simple, and order is not fixed.
(This might even work on Windows, with the recent support for Unix shells.)
Also, shockingly few Unix programmers know of this usage. :)
Upvotes: 2
Reputation: 7948
You can get command-line information from process.argv()
And I don't want to limit the problem to node.js
. Instead, I want to turn it into how to parse the string as the argument.
console.log(ArgumentParser(`--debug --msg="Hello World" --title="Test" --desc=demo -open --level=5 --MyFloat=3.14`))
output
{
"debug": true,
"msg": "Hello World",
"title": "Test",
"desc": "demo",
"open": true,
"level": 5,
"MyFloat": 3.14
}
Pure javascript, no dependencies needed
// 👇 Below is Test
(() => {
window.onload = () => {
const testArray = [
`--debug --msg="Hello World" --title="Test" --desc=demo -open --level=5 --MyFloat=3.14`,
]
for (const testData of testArray) {
try {
const obj = ArgumentParser(testData)
console.log(obj)
} catch (e) {
console.error(e.message)
}
}
}
})()
// 👇 Script
class ParserError extends Error {
}
function Cursor(str, pos) {
this.str = str
this.pos = pos
this.MoveRight = (step = 1) => {
this.pos += step
}
this.MoveToNextPara = () => {
const curStr = this.str.substring(this.pos)
const match = /^(?<all> *--?(?<name>[a-zA-Z_][a-zA-Z0-9_]*)(=(?<value>[^-]*))?)/g.exec(curStr) // https://regex101.com/r/k004Gv/2
if (match) {
let {groups: {all, name, value}} = match
if (value !== undefined) {
value = value.trim()
if (value.slice(0, 1) === '"') { // string
if (value.slice(-1) !== '"') {
throw new ParserError(`Parsing error: '"' expected`)
}
value = value.slice(1, -1)
} else { // number or string (without '"')
value = isNaN(Number(value)) ? String(value) : Number(value)
}
}
this.MoveRight(all.length)
return [name, value ?? true] // If the value is undefined, then set it as ture.
}
throw new ParserError(`illegal format detected. ${curStr}`)
}
}
function ArgumentParser(str) {
const obj = {}
const cursor = new Cursor(str, 0)
while (1) {
const [name, value] = cursor.MoveToNextPara()
obj[name] = value
if (cursor.pos === str.length) {
return obj
}
}
}
Upvotes: 4
Reputation: 1080
proj.js
for(var i=0;i<process.argv.length;i++){
console.log(process.argv[i]);
}
Terminal:
nodemon app.js "arg1" "arg2" "arg3"
Result:
0 'C:\\Program Files\\nodejs\\node.exe'
1 'C:\\Users\\Nouman\\Desktop\\Node\\camer nodejs\\proj.js'
2 'arg1' your first argument you passed.
3 'arg2' your second argument you passed.
4 'arg3' your third argument you passed.
Explaination:
C:\Program Files\nodejs\node.exe
)proj.js
)arg1
)arg2
)arg3
)your actual arguments start form second index of argv
array, that is process.argv[2]
.
Upvotes: 25
Reputation: 2265
I extended the getArgs
function just to get also commands, as well as flags (-f
, --anotherflag
) and named args (--data=blablabla
):
/**
* @module getArgs.js
* get command line arguments (commands, named arguments, flags)
*
* @see https://stackoverflow.com/a/54098693/1786393
*
* @return {Object}
*
*/
function getArgs () {
const commands = []
const args = {}
process.argv
.slice(2, process.argv.length)
.forEach( arg => {
// long arg
if (arg.slice(0,2) === '--') {
const longArg = arg.split('=')
const longArgFlag = longArg[0].slice(2,longArg[0].length)
const longArgValue = longArg.length > 1 ? longArg[1] : true
args[longArgFlag] = longArgValue
}
// flags
else if (arg[0] === '-') {
const flags = arg.slice(1,arg.length).split('')
flags.forEach(flag => {
args[flag] = true
})
}
else {
// commands
commands.push(arg)
}
})
return { args, commands }
}
// test
if (require.main === module) {
// node getArgs test --dir=examples/getUserName --start=getUserName.askName
console.log( getArgs() )
}
module.exports = { getArgs }
$ node lib/getArgs test --dir=examples/getUserName --start=getUserName.askName
{
args: { dir: 'examples/getUserName', start: 'getUserName.askName' },
commands: [ 'test' ]
}
$ node lib/getArgs --dir=examples/getUserName --start=getUserName.askName test tutorial
{
args: { dir: 'examples/getUserName', start: 'getUserName.askName' },
commands: [ 'test', 'tutorial' ]
}
Upvotes: 3
Reputation: 16164
ES6-style no-dependencies solution:
const longArgs = arg => {
const [ key, value ] = arg.split('=');
return { [key.slice(2)]: value || true }
};
const flags = arg => [...arg.slice(1)].reduce((flagObj, f) => ({ ...flagObj, [f]: true }), {});
const args = () =>
process.argv
.slice(2)
.reduce((args, arg) => ({
...args,
...((arg.startsWith('--') && longArgs(arg)) || (arg[0] === '-' && flags(arg)))
}), {});
console.log(args());
Upvotes: 4
Reputation: 808
Parsing argument based on standard input ( --key=value
)
const argv = (() => {
const arguments = {};
process.argv.slice(2).map( (element) => {
const matches = element.match( '--([a-zA-Z0-9]+)=(.*)');
if ( matches ){
arguments[matches[1]] = matches[2]
.replace(/^['"]/, '').replace(/['"]$/, '');
}
});
return arguments;
})();
Command example
node app.js --name=stackoverflow --id=10 another-argument --text="Hello World"
Result of argv: console.log(argv)
{
name: "stackoverflow",
id: "10",
text: "Hello World"
}
Upvotes: 21
Reputation: 2719
The easiest way to parse command-line arguments in NodeJS is using the stdio module. Inspired by UNIX getopt
utility, it is as trivial as follows:
var stdio = require('stdio');
var ops = stdio.getopt({
'check': {key: 'c', args: 2, description: 'What this option means'},
'map': {key: 'm', description: 'Another description'},
'kaka': {args: 1, required: true},
'ooo': {key: 'o'}
});
If you run the previous code with this command:
node <your_script.js> -c 23 45 --map -k 23 file1 file2
Then ops
object will be as follows:
{ check: [ '23', '45' ],
args: [ 'file1', 'file2' ],
map: true,
kaka: '23' }
So you can use it as you want. For instance:
if (ops.kaka && ops.check) {
console.log(ops.kaka + ops.check[0]);
}
Grouped options are also supported, so you can write -om
instead of -o -m
.
Furthermore, stdio
can generate a help/usage output automatically. If you call ops.printHelp()
you'll get the following:
USAGE: node something.js [--check <ARG1> <ARG2>] [--kaka] [--ooo] [--map]
-c, --check <ARG1> <ARG2> What this option means (mandatory)
-k, --kaka (mandatory)
--map Another description
-o, --ooo
The previous message is shown also if a mandatory option is not given (preceded by the error message) or if it is mispecified (for instance, if you specify a single arg for an option and it needs 2).
You can install stdio module using NPM:
npm install stdio
Upvotes: 86
Reputation: 1470
TypeScript solution with no libraries:
interface IParams {
[key: string]: string
}
function parseCliParams(): IParams {
const args: IParams = {};
const rawArgs = process.argv.slice(2, process.argv.length);
rawArgs.forEach((arg: string, index) => {
// Long arguments with '--' flags:
if (arg.slice(0, 2).includes('--')) {
const longArgKey = arg.slice(2, arg.length);
const longArgValue = rawArgs[index + 1]; // Next value, e.g.: --connection connection_name
args[longArgKey] = longArgValue;
}
// Shot arguments with '-' flags:
else if (arg.slice(0, 1).includes('-')) {
const longArgKey = arg.slice(1, arg.length);
const longArgValue = rawArgs[index + 1]; // Next value, e.g.: -c connection_name
args[longArgKey] = longArgValue;
}
});
return args;
}
const params = parseCliParams();
console.log('params: ', params);
Input: ts-node index.js -p param --parameter parameter
Output: { p: 'param ', parameter: 'parameter' }
Upvotes: 6
Reputation: 48230
The arguments are stored in process.argv
Here are the node docs on handling command line args:
process.argv
is an array containing the command line arguments. The first element will be 'node', the second element will be the name of the JavaScript file. The next elements will be any additional command line arguments.
// print process.argv
process.argv.forEach(function (val, index, array) {
console.log(index + ': ' + val);
});
This will generate:
$ node process-2.js one two=three four
0: node
1: /Users/mjr/work/node/process-2.js
2: one
3: two=three
4: four
Upvotes: 3743
Reputation: 647
Passing arguments is easy, and receiving them is just a matter of reading the process.argv array Node makes accessible from everywhere, basically. But you're sure to want to read them as key/value pairs, so you'll need a piece to script to interpret it.
Joseph Merdrignac posted a beautiful one using reduce, but it relied on a key=value
syntax instead of -k value
and --key value
. I rewrote it much uglier and longer to use that second standard, and I'll post it as an answer because it wouldn't fit as a commentary. But it does get the job done.
const args = process.argv.slice(2).reduce((acc,arg,cur,arr)=>{
if(arg.match(/^--/)){
acc[arg.substring(2)] = true
acc['_lastkey'] = arg.substring(2)
} else
if(arg.match(/^-[^-]/)){
for(key of arg.substring(1).split('')){
acc[key] = true
acc['_lastkey'] = key
}
} else
if(acc['_lastkey']){
acc[acc['_lastkey']] = arg
delete acc['_lastkey']
} else
acc[arg] = true
if(cur==arr.length-1)
delete acc['_lastkey']
return acc
},{})
With this code a command node script.js alpha beta -charlie delta --echo foxtrot
would give you the following object
args = {
"alpha":true,
"beta":true,
"c":true,
"h":true,
"a":true,
"r":true
"l":true,
"i":true,
"e":"delta",
"echo":"foxtrot"
}
Upvotes: 8
Reputation: 2078
Although Above answers are perfect, and someone has already suggested yargs, using the package is really easy. This is a nice package which makes passing arguments to command line really easy.
npm i yargs
const yargs = require("yargs");
const argv = yargs.argv;
console.log(argv);
Please visit https://yargs.js.org/ for more info.
Upvotes: 6
Reputation: 1729
Here's my 0-dep solution for named arguments:
const args = process.argv
.slice(2)
.map(arg => arg.split('='))
.reduce((args, [value, key]) => {
args[value] = key;
return args;
}, {});
console.log(args.foo)
console.log(args.fizz)
Example:
$ node test.js foo=bar fizz=buzz
bar
buzz
Note: Naturally this will fail when the argument contains a =
. This is only for very simple usage.
Upvotes: 35
Reputation: 51
process.argv
is your friend, capturing command line args is natively supported in Node JS. See example below::
process.argv.forEach((val, index) => {
console.log(`${index}: ${val}`);
})
Upvotes: 3
Reputation: 1951
The simplest way of retrieving arguments in Node.js is via the process.argv array. This is a global object that you can use without importing any additional libraries to use it. You simply need to pass arguments to a Node.js application, just like we showed earlier, and these arguments can be accessed within the application via the process.argv array.
The first element of the process.argv array will always be a file system path pointing to the node executable. The second element is the name of the JavaScript file that is being executed. And the third element is the first argument that was actually passed by the user.
'use strict';
for (let j = 0; j < process.argv.length; j++) {
console.log(j + ' -> ' + (process.argv[j]));
}
All this script does is loop through the process.argv array and prints the indexes, along with the elements stored in those indexes. It's very useful for debugging if you ever question what arguments you're receiving, and in what order.
You can also use libraries like yargs for working with commnadline arguments.
Upvotes: 5
Reputation: 3644
Most of the people have given good answers. I would also like to contribute something here. I am providing the answer using lodash
library to iterate through all command line arguments we pass while starting the app:
// Lodash library
const _ = require('lodash');
// Function that goes through each CommandLine Arguments and prints it to the console.
const runApp = () => {
_.map(process.argv, (arg) => {
console.log(arg);
});
};
// Calling the function.
runApp();
To run above code just run following commands:
npm install
node index.js xyz abc 123 456
The result will be:
xyz
abc
123
456
Upvotes: 1
Reputation: 2154
as stated in the node docs The process.argv property returns an array containing the command line arguments passed when the Node.js process was launched.
For example, assuming the following script for process-args.js:
// print process.argv
process.argv.forEach((val, index) => {
console.log(`${index}: ${val}`);
});
Launching the Node.js process as:
$ node process-args.js one two=three four
Would generate the output:
0: /usr/local/bin/node
1: /Users/mjr/work/node/process-args.js
2: one
3: two=three
4: four
Upvotes: 1
Reputation: 8396
command-line-args is worth a look!
You can set options using the main notation standards (learn more). These commands are all equivalent, setting the same values:
$ example --verbose --timeout=1000 --src one.js --src two.js
$ example --verbose --timeout 1000 --src one.js two.js
$ example -vt 1000 --src one.js two.js
$ example -vt 1000 one.js two.js
To access the values, first create a list of option definitions describing the options your application accepts. The type
property is a setter function (the value supplied is passed through this), giving you full control over the value received.
const optionDefinitions = [
{ name: 'verbose', alias: 'v', type: Boolean },
{ name: 'src', type: String, multiple: true, defaultOption: true },
{ name: 'timeout', alias: 't', type: Number }
]
Next, parse the options using commandLineArgs():
const commandLineArgs = require('command-line-args')
const options = commandLineArgs(optionDefinitions)
options
now looks like this:
{
src: [
'one.js',
'two.js'
],
verbose: true,
timeout: 1000
}
Beside the above typical usage, you can configure command-line-args to accept more advanced syntax forms.
Command-based syntax (git style) in the form:
$ executable <command> [options]
For example.
$ git commit --squash -m "This is my commit message"
Command and sub-command syntax (docker style) in the form:
$ executable <command> [options] <sub-command> [options]
For example.
$ docker run --detached --image centos bash -c yum install -y httpd
A usage guide (typically printed when --help
is set) can be generated using command-line-usage. See the examples below and read the documentation for instructions how to create them.
A typical usage guide example.
The polymer-cli usage guide is a good real-life example.
There is plenty more to learn, please see the wiki for examples and documentation.
Upvotes: 36
Reputation: 3850
const args = process.argv.slice(2).reduce((acc, arg) => {
let [k, v = true] = arg.split('=')
acc[k] = v
return acc
}, {})
for this command node index.js count=2 print debug=false msg=hi
console.log(args) // { count: '2', print: true, debug: 'false', msg: 'hi' }
we can change
let [k, v = true] = arg.split('=')
acc[k] = v
by (much longer)
let [k, v] = arg.split('=')
acc[k] = v === undefined ? true : /true|false/.test(v) ? v === 'true' : /[\d|\.]+/.test(v) ? Number(v) : v
to auto parse Boolean & Number
console.log(args) // { count: 2, print: true, debug: false, msg: 'hi' }
Upvotes: 21
Reputation: 317
If you want to do this in vanilla JS/ES6 you can use the following solution
worked only in NodeJS > 6
const args = process.argv
.slice(2)
.map((val, i)=>{
let object = {};
let [regexForProp, regexForVal] = (() => [new RegExp('^(.+?)='), new RegExp('\=(.*)')] )();
let [prop, value] = (() => [regexForProp.exec(val), regexForVal.exec(val)] )();
if(!prop){
object[val] = true;
return object;
} else {
object[prop[1]] = value[1] ;
return object
}
})
.reduce((obj, item) => {
let prop = Object.keys(item)[0];
obj[prop] = item[prop];
return obj;
}, {});
And this command
node index.js host=http://google.com port=8080 production
will produce the following result
console.log(args);//{ host:'http://google.com',port:'8080',production:true }
console.log(args.host);//http://google.com
console.log(args.port);//8080
console.log(args.production);//true
p.s. Please correct the code in map and reduce function if you find more elegant solution, thanks ;)
Upvotes: 5