I'm getting different results testing a simple java class on Windows cmd and wsl (ubuntu).
The java class:
public class PrintArgs {
public static void main(String[] args) {
System.out.println("Printing some arguments in this code: ");
// Loop through arguments passed and print them to standard output
for (int i = 0; i < args.length; i++) {
System.out.println("Argument " + (i + 1) + ": " + args[i]);
}
}
}
I use this test arguments:
java PrintArgs.java Test "Testing TestThis" 'Some arguments' ´More Arguments´
In cmd, the single quote doesn't group the arguments:
cmd results and java version
but in ubuntu, it does:
wsl results and java version
Any idea why this is happening?
The Java process will already get an array of strings as the argument (in anything C-based it's more like a **char, but that's close enough). It doesn't even see the quotes that group a single argument together, because those will already have been interpreted by the shell.
The shell (probably Bash in WSL and cmd.exe in the command window) is responsible for taking the single continuous string of what the user entered and splitting it into arguments (and expanding wildcards, where applicable, but that doesn't happen in this case).
Now Bash and cmd.exe have different rule about how quoting works, so they split the single string differently.
Related
I'm trying to parse my command line arguments using the apache commons CLI. It might be a bit heavy handed for the example here, but it makes sense in the context of the program I'm creating. I'm trying to read a file pattern filter, similar to what grep uses to select files to process.
My Argument looks like this:
Program --input *.*
I've written a test program to see what the parser is seeing;
public static void main(String[] args) {
Options options = new Options();
options.addOption(new Option(INPUT_FILTER_SHORT, INPUT_FILTER_LONG, true, INPUT_FILTER_DESCRIPTION));
CommandLineParser parser = new BasicParser();
CommandLine cmd = parser.parse(options, args);
System.out.println(cmd.getOptionValue(INPUT_FILTER_SHORT));
}
This prints out:
.classpath
If I change my arguments to:
Program --input test.txt
I get the output:
test.txt
I'm assuming that I have to do something to tell apache commons what * is not a special character? I can't seem to find anything about this online.
I'm experiencing this on Windows (7). I'm fairly certain it's the *.* which is causing the issue as when I swap to using patterns that don't use *, the expected pattern shows up.
Your problem isn't really to do with Commons CLI, but to do with how the shell and the Java executable together process the parameters.
To eliminate other factors, and see what's going on, use a short Java program:
public class ArgsDemo {
public static void main(String[] args) {
for(int i=0; i<args.length; i++) {
System.out.println("" + i + ": " + args[i]);
}
}
}
Play with java ArgsDemo hello world, java ArgsDemo * etc. and observe what happens.
On UNIX and Linux:
Java does no special processing of *. However, the shell does. So if you did:
$ mkdir x
$ cd x
$ touch a b
$ java -jar myjar.jar MyClass *
... then MyClass.main() would be invoked with the parameter array ["a","b"] -- because the UNIX shell expands * to files in the current directory.
You can suppress this by escaping:
$ java -jar myjar MyClass * // main() sees ["*"])
(Note that a UNIX shell wouldn't expand *.* to .classpath because this form would ignore "hidden" files starting with .)
On Windows
cmd.exe does not do UNIX-style wildcard expansion. If you supply * as a parameter to a command in Windows, the command gets a literal *. So for example, PKUNZIP *.zip passes *.zip to PKUNZIP.EXE, and it's up to that program to expand the wildcard if it wants to.
Since some release of Java 7, the Java executable for Windows does some wildcard to filename expansion of its own, before passing the parameters to your main() class.
I've not been able to find clear documentation of Java-for-Windows' wildcard expansion rules, but you should be able to control it with quoting, escaping the quotes to prevent cmd.exe interpreting them:
> java.exe -jar myjar.jar MyClass """*.*"""
(Untested as I don't have a Windows box handy, and quoting in cmd.exe is a bit of a beast - do please experiment and either edit the above or leave a comment)
package commandLine;
public class commandLine {
public static void main(String[] args) {
System.out.println("There are " +args.length+ " Command-line Arguments");
System.out.println("They are: ");
for(int i=0;i<args.length;i++){
System.out.println("arg["+i+"]: "+args[i]);
}
}
}
I wanted to check the length of my command-line arguments and loop through them to display the array of command lines. However, it says my command line arguments are 0? How can this be?
Official Java tutorial about command-line arguments.
Command-Line Arguments
A Java application can accept any number of arguments from the command
line. This allows the user to specify configuration information when
the application is launched.
The user enters command-line arguments when invoking the application
and specifies them after the name of the class to be run. For example,
suppose a Java application called Sort sorts lines in a file. To sort
the data in a file named friends.txt, a user would enter:
java Sort friends.txt
When an application is launched, the runtime
system passes the command-line arguments to the application's main
method via an array of Strings. In the previous example, the
command-line arguments passed to the Sort application in an array that
contains a single String: "friends.txt".
Echoing Command-Line Arguments
The Echo example displays each of its command-line arguments on a line
by itself:
public class Echo {
public static void main (String[] args) {
for (String s: args) {
System.out.println(s);
}
}
}
The following example shows how a user might run Echo. User input is
in italics.
java Echo Drink Hot Java
Drink
Hot
Java
Note that the application
displays each word — Drink, Hot, and Java — on a line by itself. This
is because the space character separates command-line arguments. To
have Drink, Hot, and Java interpreted as a single argument, the user
would join them by enclosing them within quotation marks.
java Echo "Drink Hot Java" Drink Hot Java
If you are using IDE (Eclipse or etc.) you have to specify command-line arguments via some kind of run configuration. For example for Eclipse:
In have the command line is essentially of the form
java [vm options] class/jar [arguments]
Only these final arguments are given to you in the array. This is unlike a standard C program where you receive the command name also.
My app launches and loads the file if I do: myApp /file:c:\nospaces.asd from cmd but if I do myApp /file:c:\with spaces.asd it won't work because the program receives two arguments: myApp /file:c:\with and spaces.asd.
I know that I can do myApp "/file:c:\with spaces.asd" and it'll work like that from cmd. However this isn't a good solution because if I double click the .asd file (custom extension) (and select launch with my app) then main won't be getting the arguments as one line but as two arguments.
How can I go about fixing this issue so that my main will receive only one argument when double clicking the file?
You could join the arguments together if the file is not found. Something like this:
public static void main(String[] args) {
String fileName = joinArgumentsToValidFileName(args);
}
public static String joinArgumentsToValidFileName(String[] args) {
if(args.length == 0) {
return "";
}
String fileName = args[0];
int index = 1;
while(!new File(fileName).exists() && index < args.length) {
fileName += " " + args[index];
index++;
}
return fileName;
}
This assumes that the first argument (or the arguments) must be the file name. Any additional agruments could be evaluated by remembering the offset index somehow (not included in the code above).
But note: This is a not standard behavior of passing arguments to an application and could lead to cunfusion. So if you find a way to pass a "" wrapped file name argument, don't do this!
Double clicking to launch java would be affected by whats registered in windows related to the same i.e windows registry for jar-file launch command.
These are some similar questions asked on SO you can take a look at:
Running JAR file on Windows
java can run jar from cmd but not by double clicking
They mention the useful part which is ensuring you have the wildcard behind the executable in the registry c:\...\javaw.exe" -jar "%1" %
Is there a way to read data from the command prompt? I have a java program that relies on 4 input variables from an outside source. These variables are returned to the command prompt after I run a javascript program but i need a way to pass these variables from the command prompt into my java program, any help would be greatly appreciated!
While executing java program pass the parameters and all the parameters should be separated by space.
java programName parameter1 parameter2 parameter3 parameter4
This parameters would be available in your main method argument
public static void main(String[] args){
//This args array would be containing all four values, i.e. its length would be 4 and you easily iterate values.
for(int i=0; i<args.length; i++){
System.out.println("Argument " + i + " is " + args[i]);
}
Follow the link:
Command-Line Arguments - The Java™ Tutorials : https://docs.oracle.com/javase/tutorial/essential/environment/cmdLineArgs.html
shared by #BackSlash.
It has all the content which would help you to clear all your doubts.
The content from the link is quoted below:
Displaying Command-Line Arguments passed by user from command-line to a Java program
The following example displays each of its command-line arguments on a
line by itself:
public class DisplayCommandLineParameters {
public static void main (String[] args) {
for (String s: args) {
System.out.println(s);
}
}
}
To compile the program: From the Command Prompt, navigate to the directory containing your .java file, say C:\test, by typing the cd
command below.
C:\Users\username>cd c:\test
C:\test>
Assuming the file, say DisplayCommandLineParameters.java, is in the
current working directory, type the javac command below to compile it.
C:\test>javac DisplayCommandLineParameters.java
C:\test>
If everything went well, you should see no error messages.
To run the program: The following example shows how a user might run the class.
C:\test>java DisplayCommandLineParameters Hello Java World
Output:
Hello
Java
World
Note that the application displays each word — Hello, Java and World —
on a line by itself. This is because the space character separates
command-line arguments.
To have Hello, Java and World interpreted as a single argument, the
user would join them by enclosing them within quotation marks.
C:\test>java DisplayCommandLineParameters "Hello Java World"
Output: Hello Java World
Here is a strange problem I ran into:
I create a single program to print all the received args, Here is the code:
public class Test {
public static void main(String[] args) {
for (int i = 0; i < args.length; i ++) {
System.out.println(args[i]);
}
}
}
Then I built a jar file of it and ran the following command:
java -jar test.jar test&1
However, it didn't print "test&1" as expected. The result of it is:
test
'1'is not recognized as an internal or external command,operable program or batch file.
So my question is: what is the seperation of args? If I really need to receive "test&1", what should I do?
Thanks!
It's nothing to do with Java. The & character is special to the Windows shell (I can tell it's Windows from the error message): It separates two commands on one line, so what you're doing is telling the shell to run java -jar test.jar test and then run 1. If you want to pass test&1 to Java, you'll have to put it in quotes:
java -jar test.jar "test&1"
The & is also special on *nix shells (but in a different way, it runs the command in a sub-shell). There, you could use quotes as above, or put an \ before the & instead. But not on Windows.