6

Here is the groovy script:

param = args[0]
println(param)

Here is how I run it (Windows 7):

groovy test.groovy a&b

I expect this script prints a&b, but instead get 'b' is not recognized as an internal or external command, operable program or batch file.

I tried to put the argument (a&b in my case) in quotes but it doesn't help. With double quotes, the script hangs. With single quotes I get the same error like without any quotes.

Question: is it possible to take a string with ampersand as command line argument for groovy script?

Racoon
  • 951
  • 3
  • 14
  • 32
  • Is that message coming from groovy itself or from windows shell? On MacOS it works perfectly fine with the following invocation: `groovy script.groovy a\&b` – Opal Nov 05 '14 at 17:30
  • Opal, it comes from windows shell. With a\&b, I have the same error: 'b' is not recognized as an internal or external command, operable program or batch file. – Racoon Nov 05 '14 at 17:32
  • 1
    reproduced it. this is a windows command-line thing. there are a bunch of suggested fixes involving escaping with carat and using double-quotes, none of them seem to work. – Nathan Hughes Nov 05 '14 at 17:39
  • Nathan, agree, I tried carat, backslash and quotes. Nothing worked. Am I the only person in the world who needs it? – Racoon Nov 05 '14 at 17:40
  • 1
    just have tried `groovy test a^&b` and it did not work? what "shell" are you using in windows? just plain `cmd` or something else? i really doubt, that this is a groovy problem – cfrick Nov 05 '14 at 19:21
  • cfrick, sure, I have tried a^&b and it didn't work. I am using plain cmd and it doesn't work. I think it's kind of a mixed problem, since ^ does work in plain batch scripts but doesn't work when & is used in cmdline parameter for groovy script. – Racoon Nov 05 '14 at 19:56
  • 2
    to address a comment to someone, so that they get notified, put an @ before their name. – Nathan Hughes Nov 06 '14 at 03:12
  • but the error message is the one from windows. how would groovy ever print something like this? does the quoting work if you do e.g. `dir a^&b`? – cfrick Nov 06 '14 at 09:18
  • @cfrick, sure, the error message is from windows, but it doesn't help to solve the problem. When I do dri a^&b, I don't get this error ('b' is not recognized bla-bla-bla), just the "File not found" which is expected. – Racoon Nov 06 '14 at 09:39
  • 1
    i'd drop the java tag, add windows-oid tags and see if this attracts attention in the windows crouds here on SO. – cfrick Nov 06 '14 at 10:03

1 Answers1

5

When executing groovy on Windows, we actually execute %GROOVY_HOME\groovy.bat and then (from groovy.bat):

"%DIRNAME%\startGroovy.bat" "%DIRNAME%" groovy.ui.GroovyMain %*

If we look inside startGroovy.bat, we can see a really ugly hack to deal with arguments (excerpt below):

rem horrible roll your own arg processing inspired by jruby equivalent

rem escape minus (-d), quotes (-q), star (-s).
set _ARGS=%*
if not defined _ARGS goto execute
set _ARGS=%_ARGS:-=-d%
set _ARGS=%_ARGS:"=-q%
set _ARGS=%_ARGS:?=-n%

rem Windowz will try to match * with files so we escape it here
rem but it is also a meta char for env var string substitution
rem so it can't be first char here, hack just for common cases.
rem If in doubt use a space or bracket before * if using -e.
set _ARGS=%_ARGS: *= -s%
set _ARGS=%_ARGS:)*=)-s%
set _ARGS=%_ARGS:0*=0-s%
set _ARGS=%_ARGS:1*=1-s%
set _ARGS=%_ARGS:2*=2-s%
set _ARGS=%_ARGS:3*=3-s%
set _ARGS=%_ARGS:4*=4-s%
set _ARGS=%_ARGS:5*=5-s%
set _ARGS=%_ARGS:6*=6-s%
set _ARGS=%_ARGS:7*=7-s%
set _ARGS=%_ARGS:8*=8-s%
set _ARGS=%_ARGS:9*=9-s%

Therefore, inside startyGroovy.bat "a&b" is "escaped" to -qa&b-q, resulting in two commands inside the script, yielding

'b-q' is not recognized as an internal or external command,
operable program or batch file.

and causing an infinite loop while "unescaping".

You can see it with set DEBUG=true before running your groovy script.

Adding another hack to the bunch of hacks, you can escape also & in a similar way in startGroovy.bat as follows:

rem escape minus (-d), quotes (-q), star (-s).
rem jalopaba escape ampersand (-m)
set _ARGS=%*
if not defined _ARGS goto execute
set _ARGS=%_ARGS:-=-d%
set _ARGS=%_ARGS:&=-m%
set _ARGS=%_ARGS:"=-q%
set _ARGS=%_ARGS:?=-n%

and unescape...

rem now unescape -s, -q, -n, -d
rem jalopaba unescape -m
rem -d must be the last to be unescaped
set _ARG=%_ARG:-s=*%
set _ARG=%_ARG:-q="%
set _ARG=%_ARG:-n=?%
set _ARG=%_ARG:-m=&%
set _ARG=%_ARG:-d=-%

So that:

groovy test.groovy "a&b"
a&b

Not sure if a clearer/more elegant solution is even posible in Windows.

You can see a similar case with groovy -e "println 2**3" that yields 8 in UNIX console but hangs (infinite loop) in windows.

jalopaba
  • 8,039
  • 2
  • 44
  • 57
  • thank you very much for the valuable comment! I tried this option earlier, but in my environment (Windows 7 x64) groovy test.groovy "a&b" just hangs... – Racoon Nov 06 '14 at 13:54
  • let me go into it more deeply. It looks like I was wrong in escaping &. I will try more. – Racoon Nov 06 '14 at 13:58