18

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?

philwalk
  • 571
  • 1
  • 5
  • 14
Nithismiles
  • 189
  • 1
  • 1
  • 4
  • I removed the java tag, because it's a universal problem, not related to Java. You can start your Java program without problem from somewhere, where no globbing takes place (another Java program, for example). – user unknown Apr 11 '11 at 09:34
  • what operating system are you using? what's the exact command executed? – Dropout Jul 13 '15 at 13:41
  • 1
    If running from a cygwin bash shell, the solutions below don't work (quoting or escaping the asterisk) since the jvm globs a trailing asterisk internally, although the circumstances that trigger it are not clear (to me, at least). See Arno's entry below. – philwalk May 06 '16 at 19:37

5 Answers5

31

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 (\).

polygenelubricants
  • 348,637
  • 121
  • 546
  • 611
  • 1
    For completeness, and since the OP didn't mention any particular operating system, note that in Windows globbing is the responsibility of the application, not the shell. It is typically handled by the application's runtime library. – Harry Johnston Jun 05 '14 at 22:30
  • it turns out that the Windows jvm performs its' own globbing internally under some circumstances, see http://stackoverflow.com/questions/37037375 – philwalk May 06 '16 at 19:35
4

* 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 "*".

Zhaojun
  • 1,119
  • 1
  • 6
  • 4
4

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?

Arno Unkrig
  • 131
  • 4
  • I agree, this feature can be nasty, but it's a practical requirement if java command line tools are to be relatively OS-agnostic. However, there doesn't seem to be any system.property to disable it, and that makes it quadruple nasty (sigh). – philwalk May 06 '16 at 18:29
  • 1
    BTW, you can double quote the asterisk from within a cmd.exe session and it does what you would expect, but if running from within a cygwin BASH session, there doesn't seem to be any way of doing the same thing. The weird part is I've verified that the problem occurs somewhere in java, not in the shell environment (as you said). See my notes here: http://stackoverflow.com/questions/37037375 – philwalk May 06 '16 at 18:41
  • 2
    this issue also turns up calling from PowerShell, regardless of escaping/quoting – Hashbrown Nov 22 '17 at 02:18
2

Try surrounding the * with quotes like "*". The star is a reserved symbol on the command line.

1

Use single quotes:

java FooBar 5 3 '*'

This works with most of the popular shells (including bash and ksh).

Dávid Horváth
  • 3,376
  • 1
  • 18
  • 29