When we want to execute shell command in Nodejs, we can using exec
or spawn
method from child_process
module, and it works often. However, when we have some special char in our command, such as ()
or spaces will cause error. So how can we escape our command args to make it right
Basic shell
when we execute command in shell, we should escape it by ourself. Such as we have a file named by abc(1).txt
, when we want to cat it, we should escape (
and )
in shell.
cat abc\(1\).txt
In shell, there are some special chars that required to be escaped when it appear in command line. List as below:
$!'"();`*?{}[]<>&%#~@\
and include spaces.
Escape Command in Nodejs
Now, we know that the basic shell escape way, how can we do it in nodejs, when we have special char in our command that will be executed by exec
or spawn
method.
const { exec } = require('child_process')
const command = ['cat', 'abc(1).txt']
const shellEscape = (arg: string): string => {
if (/[^A-Za-z0-9_\/:=-]/.test(arg)) return arg.replace(/([$!'"();`*?{}[\]<>&%#~@\\ ])/g, '\\$1')
return arg
}
//console.log(command.map(shellEscape).join(' ')) => cat abc\(1\).txt
exec(command.map(shellEscape).join(' '))
The shellEscape
function get the each command line arg, and using the /[^A-Za-z0-9_\/:=-]/
regex to test whether the arg contains special char, if true, replace the special char with \\$1.
We should add \
before the special char to escape, why we have two \\
before. Since the \
itself is also a special char, we should escape it two to make \\
represents \
in command args at last.
And the $1
means the matching special char in the pattern.
For the a(1).txt
, after shell escape will resulted be a\\(1\\).txt
, console it will get the real arg a\(1\).txt.
If the arg doesn’t contain any special char, the shellEscape
function will return it directly.
Conclusions
If you are using nodejs to execute some shell command with dynamic args, you should using the shellEscape
function to make sure the args be escaped. You can safely to do it with any args. Happy executing any commands with special chars in it.
Thanks for reading it. If anything wrong, please point it out.