Suppose I'm on MacOS, and open up iterm2 and I type in the following command:
java Foo.java "Hello World" "bar"
In the main method of Foo.java, it receives a String array of ["Hello World", "bar"].
What software component handles the splitting of the command-line string? As in the part that takes into account quotes, double quotes, escaped quotes, spaces and returns a list of parameters? Is it the Java Runtime? Is it the terminal emulator? Is it the shell? And is this different on other platforms? E.g. Linux Distros, Windows?
Related
Ex:
cmd /C start C:\Users\Bob Builder\Desktop\New Folder\test.exe
I'm trying to use cmd to start a file but since there are spaces in the path, cmd is throwing an error after Bob.
Error:
"Windows cannot find C:\Users\Bob. Make sure you typed the name
correctly, then try again."
The system cannot find the file C:\Users\Bob.
Its simply failing to accept the spaces. It's driving me crazy because I'm spoiled with C# working out of the box. I don't know much about this, I have been spending way too much time trying to figure this out. Some help would be greatly appreciated.
In order for a path that contains spaces to be recognized as a single path (argument), it must be quoted.
In order for an executable to execute in the current console window, synchronously, with its streams connected to the calling shell, it must be invoked directly, not via start.
Direct invocation from cmd.exe (only "..." quoting supported):
"C:\Users\Bob Builder\Desktop\New Folder\test.exe"
From PowerShell:
& 'C:\Users\Bob Builder\Desktop\New Folder\test.exe'
Note:
PowerShell also supports '...' strings (single-quoted), which are verbatim strings that are preferable to "..." (double-quoted) ones if you do not require expansion of variables (string interpolation) - see the conceptual about_Quoting_Rules help topic.
For syntactic reasons, PowerShell requires the use of &, the call operator to invoke commands that are quoted and/or contain variable references - see this answer for details.
By contrast, use start in cmd.exe / Start-Process in PowerShell (whose built-in alias is also start) to launch an executable in a new window (on Windows), asynchronously, with no (direct) ability to capture the launched executable's output:
From cmd.exe:
start "title" "C:\Users\Bob Builder\Desktop\New Folder\test.exe"
Note:
Specifying "title" - i.e. a self-chosen (console) window title - is required for syntactic reasons in this case: without it, the double-quoted path itself would be interpreted as the window title, and the - implied - executable to launch would be another cmd.exe instance.
Note that if you launch a GUI application this way, the title argument is irrelevant, because no new console window is created.
Conversely, if you launch a console application specified by double-quoted path and therefore must use a title argument, note that "" will result in the new window having no title.
From PowerShell (parameter -FilePath is positionally implied):
Start-Process 'C:\Users\Bob Builder\Desktop\New Folder\test.exe'
Note:
Start-Process does not support specifying a window title, so you may want to call cmd.exe's internal start command for that (or other features not supported by Start-Process, such as specifying the process priority).
To work around quoting problems, invoke cmd.exe's start from PowerShell by passing the entire start command as a single string to cmd /c:
cmd /c 'start "title" "C:\Users\Bob Builder\Desktop\New Folder\test.exe"'
cmd /C start "C:\Users\Bob Builder\Desktop\New Folder\test.exe"
Quotes are your friend. Sometimes even double quotes are too!
Seems like cmd won't work for me. Powershell worked with this script:
$env:Path += ";C:\Users\Bob Builder\Desktop\New Folder\"
test.exe
I am trying to execute the below command on powershell, but the encryption password is not recognised.
This password is used in integration tests.
gradle publish -Djasypt.encrypt.password = $xyz!#
The below command also does not work
cmd /c gradle publish -Djasypt.encrypt.password = $xyz!#
The same command works well on CMD
Any suggestions on passing the arguments (with -D)?
$ is the sigil denoting a variable in PowerShell just like most other shells, so $xyz means the variable named xyz. You need to escape that symbol with a backtick
gradle publish -Djasypt.encrypt.password = `$xyz!#
Alternatively just quote the string with a single quote to prevent variable substitution
gradle publish -Djasypt.encrypt.password = '$xyz!#'
I have a perl script as below, where I want to access a network path on a remote windows machine from a linux machine using rsh.
$cmd = "rsh -l $username $host \"pushd \\\\network\\path\\to\\the\\directory && dir\"";
print $cmd, "\n";
print qx($cmd);
When I run the script the third line prints output The system cannot find the path specified. However, if I run the command printed by the second line directly from the terminal it works fine.
I'm not able to understand why the script is not working. If the command works from the terminal, it should work using qx() too.
While you escape your meta-characters against interpolation by double-quotes and by the remote shell, qx might itself interpolate the string again, in which case you might need to add another level of escaping. From the documentation of qx:
A string which is (possibly) interpolated and then executed as a system command with /bin/sh or its equivalent. ...
How that string gets evaluated is entirely subject to the command interpreter on your system. On most platforms, you will have to protect shell metacharacters if you want them treated literally. This is in practice difficult to do, as it's unclear how to escape which characters. See perlsec for a clean and safe example of a manual fork() and exec() to emulate backticks safely.
I'm trying to debug a program in Eclipse so that the command-line arguments will correspond to the following invocation from the shell
[joeuser#host]$ myapp "foo<bar>" -v
Now, specifying the arguments as
-v "foo<bar>"
in the Eclipse Debug Configuration dialog does not work - there's a bash message on the console saying:
/bin/bash: bar: No such file or directory
i.e. the quotation marks get eaten away. I've tried:
escaping the angle-brackets with backslash
escaping the angle-brackets with double-backslashes
escaping the double-quotation marks
using single quotation marks
and probably some other options - none worked. Now, supposedly, there are "simple rules" on how this is to be done, being one of the answers to this question:
Eclipse & quotes in command line arguments?
but that doesn't seem very simple to me, or perhaps I am simpler than those rules. Why can't it just build a string with the command and all of the arguments, unescaped and unsanitized, and just let bash do whatever it does always? :-(
PS - I'm using Eclipse CDT 8.8.1 (Mars.2) on Debian Stretch.
I can use system in Perl 5 to run external programs. I like to think of system like a miniature "Linux command line" inside Perl. However, I cannot find documentation for system in Perl 6. What is the equivalent?
Perl6 actually has two commands that replace system from Perl 5.
In Perl6, shell passes its argument to the shell, similar to Perl 5's system when it has one argument that contains metacharacters.
In Perl6, run tries to avoid using the shell. It takes its first argument as a command and the remaining arguments as arguments to that command, similar to Perl 5's system when it has multiple arguments.
For example:
shell('ls > file.log.txt'); # Capture output from ls (shell does all the parsing, etc)
run('ls','-l','-r','-t'); # Run ls with -l, -r, and -t flags
run('ls','-lrt'); # Ditto
See also this 2014 Perl 6 Advent post on "running external programs".
In addition to using shell or run, which replace system from Perl 5, you can also use NativeCall to invoke the libc system function.
On my Windows box, it looks like this:
use NativeCall;
sub system(Str --> int32) is native("msvcr110.dll") { * };
system("echo 42");