console.log(process.argv);
The above will show the issue in a console application run from PowerShell.
If:
then the backslash will escape the final quote, which will be included in the argument value.
Example:
node foo "C:\Program Files\"
[ 'C:\\Program Files\\nodejs\\node.exe',
'C:\\SourceCode\\foo\\foo.js',
'C:\\Program Files"' ]
Note that the final argument ends with a double-quote instead of a backslash.
FWIW, shell commands and batch files process such arguments properly:
> echo "C:\Program Files\"
"C:\Program Files\"
test.bat:
echo %1
> test.bat "C:\Program Files\"
> echo "C:\Program Files\"
"C:\Program Files\"
/cc @nodejs/platform-windows
@vsemozhetbyt can you confirm that this happens on master?
Cannot reproduce on MacOS.
➜ out/Release/node ~/Code/temp/node/cli.js "/dev/null"
[ '/Users/ryzokuken/Code/nodejs/node/out/Release/node',
'/Users/ryzokuken/Code/temp/node/cli.js',
'/dev/null' ]
Yes, this happens with 6.14.3, 8.11.3, 10.6.0 and 11.0.0-nightly20180717ab10bfe376.
Tested in Windows 7 x64 on cmd.exe.
Not a Node.js issue. This is how PowerShell and cmd parse arguments. Same behavior in Python.
The logic of actually setting the value is fairly trivial and fool-proof:
// process.argv
Local<Array> arguments = Array::New(env->isolate(), argc);
for (int i = 0; i < argc; ++i) {
arguments->Set(i, String::NewFromUtf8(env->isolate(), argv[i]));
}
process->Set(FIXED_ONE_BYTE_STRING(env->isolate(), "argv"), arguments);
Perhaps there's something wrong with the argv value supplied itself?
@seishun thanks for the clarification.
Refs: https://ss64.com/nt/syntax-esc.html
Some commands (e.g. REG and FINDSTR) use the standard escape character of \ (as used by C, Python, SQL, bash and many other languages.)
The \ escape can cause problems with quoted directory paths that contain a trailing backslash because the closing quote " at the end of the line will be escaped \".
To save a directory path with a trailing backslash (\) requires adding a second backslash to 'escape the escape'
so for example instead of "C:\My Docs\" use "C:\My Docs\\"
@seishun If this is a PowerShell bug, why does this work correctly?
Get-ChildItem "C:\Program Files\"
Directory: C:\Program Files
Mode LastWriteTime Length Name
---- ------------- ------ ----
d----- 5/4/2018 11:12 PM 7-Zip
...
Get-ChildItem is a PowerShell intrinsic. Try it with any executable.
The similar issue with FINDSTR:
> cat test.txt
"C:\Program Files\"
> FINDSTR "C:\Program Files\\" test.txt
"C:\Program Files\"
> FINDSTR "C:\Program Files\" test.txt
The last commannd just waits for inputs (processing all the parameters as a one string?)
I have confirmed that @seishun is correct - this is a bug in PowerShell.
foo.c:
#include<stdio.h>
int main(int argc, char *argv[])
{
if (argc >= 2)
printf("%s", argv[1]);
return 0;
}
Compiled with Microsoft C/C++ compiler v19.14.26433 for x86 to foo.exe
./foo "C:\Program Files\"
C:\Program Files"
I apologize for the erroneous bug report.
Opened issue with PowerShell: https://github.com/PowerShell/PowerShell/issues/7400
Most helpful comment
I have confirmed that @seishun is correct - this is a bug in PowerShell.
foo.c:
Compiled with Microsoft C/C++ compiler v19.14.26433 for x86 to foo.exe
./foo "C:\Program Files\"C:\Program Files"I apologize for the erroneous bug report.