I wrote a program in Java that accepts input via command line arguments.
I get an input of two numbers and an operator from the command line.
To multiply two numbers, I have to give input as e.g. 5 3 *, but it's not working as written.
Why is it not accepting * from the command line?
That's because * is a shell wildcard: it has a special meaning to the shell, which expands it before passing it on to the command (in this case, java).
Since you need a literal *, you need to escape it from the shell. The exact way of escaping varies depending on your shell, but you can try:
java ProgramName 5 3 "*"
Or:
java ProgramName 5 3 \*
By the way, if you want to know what the shell does with the *, try printing the content of String[] args to your main method. You'll find that it will contain names of the files in your directory.
This can be handy if you need to pass some filenames as command line arguments.
See also
Wikipedia: glob
For example, if a directory contains two files, a.log and b.log then the command cat *.log will be expanded by the shell to cat a.log b.log
Wikipedia: Escape character
In Bourne shell (sh), the asterisk (*) and question mark (?) characters are wildcard characters expanded via globbing. Without a preceding escape character, an * will expand to the names of all files in the working directory that don't start with a period if and only if there are such files, otherwise * remains unexpanded. So to refer to a file literally called "*", the shell must be told not to interpret it in this way, by preceding it with a backslash (\).
Under MS WINDOWS not quite true: "java.exe" silently expands command line arguments with the wildcards
*
?
[abc]
, but only in the last component, so
a/*/*
does not work as you may expect.
It also ignores the entries "." and "..", but does honor other file names starting with ".".
To avoid misunderstandings: If I look at the command line of the running JAVA process with PROCEXP, I see the unexpanded args!
I found no way to work around this. In other words: As long as you have at least one file or directory in the current directory, "java Calc 3 * 7" will NOT work!
This is VERY ugly, and seems to always having been there in all JRE versions up to and including Java 8.
Does anybody have an idea how to disable Java's nasty command line expansion?
* has special meaning in shell interpreters. How to get a * literally is depending on what shell interpreter you are using. For Bash, you should put single quotes around the *, i.e. '*', instead of double quotes like "*".
Try surrounding the * with quotes like "*". The star is a reserved symbol on the command line.
Use single quotes:
java FooBar 5 3 '*'
This works with most of the popular shells (including bash and ksh).
Expanding on #Arno Unkrig's answer:
On Windows, some JVMs definitely do expand the "*" character, and it is not the shell expanding the path. You can confirm this by writing a small Java program that prints out the arguments:
public class TestArgs {
public static void main(String[] args) {
for (int i = 0; i < args.length; i++) {
System.out.println("Arg " + i + ": " + args[i]);
}
}
}
The good news is, there is a workaround! You can use #filename as an argument to JVM like this:
java #args.txt where args.txt is a text file that contains the arguments for each line. Example content:
TestArgs
*
This is equivalent to calling java with two arguments TestArgs and *. Most importantly, * is not expanded when it is included using the #filename method. I was able to find the details from this page.
Related
I am new in Java and I want program to get as argument a different sign. For example:
java program #
And in program I convert string to char like this:
char c = args[0].charAt(0);
or like this:
char [] c = args[0].toCharArray();
But when I put *, it doesn't work. I print and get D or even name of file.
When you use * character in the command line, it becomes expanded - that's why you get a filename/list of filenames.
You may try escaping asterisk:
using backslash \ : java program \*
using double quotes " (which should also be escaped): java program \"*\"
However, in both cases you're likely to get the asterisk along with the escape character.
Other solutions to similar issue are shown here.
I want some code in my program to run only if the user has input the character '*' at the command-line as a command-line argument. This is the code I've used:-
//myfile.java
import java.io.*;
public class myfile {
public static void main(String[] args) {
if(args[0].equals("*")){
//do stuff
System.out.println(args[0]);//added this line to see what exactly was being passed
}
}
}
When this program is executed at the command-line by entering:-
java myfile *
the output I'm expecting to see on the screen is the asterisk character, instead the output displayed is 'myfile.class'. Where am I going wrong? Why does Java change the asterisk to the .class file?
Also, note that the program worked perfectly the first four times I executed it and then started doing this!
Thanks in advance for your help.
Where am I going wrong?
The star character needs to be quoted or escaped. Run your java program like this:
java myfile "*"
or
java myfile \*
Why does Java change the asterisk to the .class file?
It doesn't. It is your shell that is doing it. It is shell file expansion ... or "globbing" as it is also called.
Run "ls *" or "echo *" and you will see that the same thing happens.
The command terminal already replaces the asterisk and java already gets the value that you see. I'd use any other character, that has no special meaning to the command terminal or otherwise you must escape the asterisk in your command.
Actually escaping arguments on Windows and especially in cmd.exe is non-trivial. This nice article explains it in detail: Everyone quotes command line arguments the wrong way :
the takaway for your case is: surround the asterisk with quotes.
Answer to your question in the comment:
Using the escape character worked! But I still don't get why it worked without the escape character the first few times
I am not sure, but maybe you run into this behavior: It makes a difference if the pattern can be expanded or not. For example, when I pass Test* as argument, then there are 2 cases to consider:
in the current folder there is a file called Test1.txt: then your java program will get Test1.txt as argument
when there are no matching files, your program will get Test* as argument
However, I am not sure, how this would apply to your case, since you only pass *: that should only work in an empty directory.
I'm a beginner in Java programming and while i was trying to create a calculator i've come across this problem: the powershell manages to read every character properly except for the asterisk, i've tried writing it in many ways: *, "*", '*' but it still acts as a wildcard character and not as a proper asterisk. How do i fix this?
Example: If I write
java Calculator 1 2 *
java Calculator 1 2 "\*"
java Calculator 1 2 '*'
none of these work and it always gets the asterisk as a wildcard character.
Your problem is not related to PowerShell per se, because it passes * through - however, it does so without quoting, whether you use *, "*", or '*'.
Therefore, the question is: What kind of quoting of * does your target program require for it to treat * as a literal rather than as a glob (wildcard expression)?
For instance, if you need to ensure that your target command sees the * as "*", you must use literal (embedded) double quotes:
java Calculate 1 2 `"*`" # `" escapes a literal "
or, using single quotes with embedded literal " instances:
java Calculate 1 2 '"*"'
Note that since Powershell doesn't recognize \ as an escape character, using \* as-is would suffice to pass literal character sequence \* - unquoted - to java.
Optional background information:
PowerShell - unlike POSIX-like shells (in the Unix world) - does not itself automatically expand (unquoted) wildcard-like arguments such as * to matching filenames (it is up to the target commands to interpret such wildcards).
Therefore, when you call external utilities such as java, tokens such as * are passed through.
However, whether you use * unquoted or whether you quote it as '*' or "*" makes no difference in this case, because PowerShell, after it has performed its own parsing, rebuilds the command line, using (double)-quoting around the arguments only if needed.
Token * needs no quoting, because it has no embedded whitespace, therefore, all 3 variations of your command result in the exact same command line when java is invoked: something like c:\path\to\java Calculator 1 2 *
Therefore, the only way to guarantee that an external utility sees an argument as "-enclosed, for instance, is to make the " chars. a literal part of the argument, as demonstrated above.
Have you tried using the escape Character "\*" ?
For example:
java Calculator 1 2 \*
I am trying to get this simple program to work but I'm not sure what I'm doing wrong; I tried making a new file to see if the problem was with my syntax but it's still happening. Here it is:
public class test {
public static void main(String[] args) {
String operator = args[0];
switch(operator) {
case "*":
System.out.println("Hello");
break;
}
}
}
I'm trying to run this program on my terminal by first doing
$ javac test.java
and then actually running the program along with the argument
$ java test *
and I get nothing after that, any reason why? It seems to work when "*" is replaced with "+".
I also noticed that it would only work if I typed out
$ java test "*" //notice the quotation marks
Why does the asterisk without the parenthesis not work even though it is a string but "+" without the parenthesis works? Is there something I am missing?
The problem is nothing to do with Java. The problem happens because the shell will treat the * character as a filename pattern and expand it to the names of all files in the current directory.
The solution is to escape the * character on the command line. There is nothing that you can do in Java to solve this.
There are a three ways that will work as escaping (for a POSIX compliant shell)
java test "*"
java test '*'
java test \*
There may be other obscure ways to do this .... but the above should suffice.
(The difference between "*" and '*' is that they escape different shell constructs. Double quotes disable just "globbing" of file pathnames. Single quotes also disable parameter substitution and other things.)
Characters that may be need to be escaped if you use them in command line arguments include:
*, ?, [, ], ~, {, } - used in globbing, etc
$ - parameter substitution
shell symbols |, &, ;
# - the comment character
the backquote character.
You should refer to a tutorial or textboox on the shell, or read the manual entry for the shell you are using.
I have a program that takes in a string as parameter and the searches the string in a text file.
Everything works perfectly except when I enter * as the parameter. It prints out all the file name in my directory. Seems it doesn't go through the code when I enter * as the parameter.
Anyone know whats going on?
You are most likely passing a glob of files from the command line. This link might be of interest:
http://en.wikipedia.org/wiki/Glob_(programming)#Syntax
Basically, when you say
java ... *
The * character is expanded (by your shell) into a list of files in the current directory. This happens before java even sees the * character, and java instead sees "file1 file2 ...".
It may help to surround the * character with single quotes on the command line, like this:
'*'
or by escaping it:
\*
Your shell is expanding the * before it gets to your program. Try escaping it like so
bash$ java MyClass \*
- * has a special meaning in Regular expressions.
- So you must use \\ before it.
Eg:
\\*