how to escape star in bash variable used for program arguments - bash

I have a variable that has program arguments to my java command with the classpath to include all jars in a directory, but I am not able to escape the asterisk correctly so keep getting main class not found error.
Here are few examples. lib/ contains all my jars. test.Main contains main() class.
Inline works as expected:
java -classpath lib/* test.Main
However, all these attempts failed:
# 1)
PRARGS="-classpath lib/*" test.Main
java $PARGS
# 2)
PRARGS="-classpath lib/*" test.Main
java "$PARGS"
# 3)
PRARGS="-classpath lib/\*" test.Main
java $PARGS
# 4)
PRARGS="-classpath lib/\*" test.Main
java "$PARGS"

An alternative to escaping star is to disable path expansion.
Try this:
PRARGS="-classpath lib/* test.Main"
set -o noglob
java $PRARGS
set +o noglob

Related

Why does Gradle's javaexec behave differently from running Java directly?

I am trying to integrate the generation of REST-API client code via the openapi-generator through Gradle. Using the openapi-generator-gradle-plugin at first, I found some bugs that make it impossible to achieve what I want, so I thought I might just download the JAR of the openapi-generator-cli in order to define a Gradle task with javaExec that will execute the generator for me.
The task looks is defined as:
build.gradle.kts
task("generate") {
javaexec {
main = "-jar"
args = listOf(
"$rootDir\\openapi-generator-cli.jar",
"generate",
"--skip-validate-spec",
"-g kotlin",
"-i $rootDir\\spec\\api.yml",
"-o $rootDir\\lib",
"-c $rootDir\\generate-kotlin.json"
)
}
}
However, when running the generate task, execution fails with
C:\work\kotlin\myapi\generate-kotlin.json (The filename, directory name, or volume label syntax is incorrect)
This is where things get strange, as I can see no issue with the path to the file in question.
I then activated debugging output for the task to see the actual command executed by Gradle. It is (formatted for readability):
C:\Program Files\Java\jdk1.8.0_202\bin\java.exe ^
-Dfile.encoding=windows-1252 ^
-Duser.country=DE ^
-Duser.language=de ^
-Duser.variant ^
-jar C:\work\kotlin\myapi\openapi-generator-cli.jar generate ^
--skip-validate-spec ^
-g kotlin ^
-i C:\work\kotlin\myapi\spec\api.yml ^
-o C:\work\kotlin\myapi\lib ^
-c C:\work\kotlin\myapi\generate-kotlin.json
To me, everything looks perfectly fine in that command. To test, I copy-pasted it to a CMD and it ran right away without any errors.
Despite the question being a bit centered around openapi-generator, as I can run the command perfectly fine manually, I assume this to be a problem with Gradle and would really like to know why it is receiving this error when the command it runs has no issues whatsoever?
I really don't want to write command-line scripts for people to execute when I could let Gradle do what I want to do.

Kotlin - System.getProperty cannot resolve command line argument

I have some code to load application.properties dynamically:
fun loadDefaultProperties(): Properties {
val configPath = System.getProperty("spring.config.location")
val resource = FileSystemResource(configPath)
return PropertiesLoaderUtils.loadProperties(resource)
}
But when I run the command...
java -jar my.jar -Dspring.config.location=my/location/application.properties
...System.getProperty("spring.config.location") returns null, and therefore, I get an IllegalArgumentException because the path is null.
Why am I unable to read the argument from the command line?
You're passing them in the wrong sequence. Pass them like:
java "-Dspring.config.location=my/location/application.properties" -jar my.jar
Otherwise they are program arguments. I've just tested it, and on MacOS, both the above as well as
java -Dspring.config.location=my/location/application.properties -jar my.jar
(without quotes) work.
Don't you need quotes?
java -jar my.jar -Dspring.config.location="my/location/application.properties"

Jacl - What is the proper syntax for variable use in an option specifier

In attempting to run the following command in a Jacl script (with $APPNAME having been set prior to this call):
$AdminApp install $EARFILE {-nopreCompileJSPs -distributeApp -nouseMetaDataFromBinary -nodeployejb -verbose -appname $APPNAME -createMBeansForResources -noreloadEnabled ...}
I get the following error.
WASX7017E: Exception received while running file "deploy_myk.jacl"; exception information: com.ibm.ws.scripting.ScriptingException: WASX7108E: Invalid data specified for install task: "AppDeploymentOptions."
Errors are:
"ADMA0085E: A validation error occurred in task Specifying application options. Application name, $APPNAME, is not valid.
An application name cannot begin with a dot, cannot have leading or trailing spaces, cannot contain "]]>", and cannot contain any of the following characters: \ / , # $ # : ; " * ? < > | = + & % '"
I seem unable to find the docs that shed light on the use of script variables within an 'option' specifier string. Clearly there must be some way to do what I'm trying to do, which is deploy an EAR file with a name of my choosing at the time the script is run
Jacl/Tcl is a string-based language, and the {} delimiter prevents variable interpolation, similar to '' in UNIX shell programming. You want something like:
$AdminApp install $EARFILE "-nopreCompileJSPs -distributeApp -nouseMetaDataFromBinary -nodeployejb -verbose -appname $APPNAME -createMBeansForResources -noreloadEnabled ..."
...or:
$AdminApp install $EARFILE [list -nopreCompileJSPs -distributeApp -nouseMetaDataFromBinary -nodeployejb -verbose -appname $APPNAME -createMBeansForResources -noreloadEnabled ...]
This Tcl tutorial might be of interest, particularly the "Evaluation & Substitutions" section.
Alternatively, you could avoid the complexities of Jacl strings by switching to -lang jython.
The variable you are using must be set before you use it. As you have not included any details about you actually doing that I assume that is what is missing. In your script you should be able to start with something like:
# Set $APPNAME to be the first argument to this script.
set APPNAME [lindex $argv 0]
And then go from there. Then you can run your jacl script with your application name as the first argument.

How can I get $ not escaped in application default jvm args for gradle?

Using the application task I am specifying:
applicationDefaultJvmArgs = ['$DEBUG_OPTS',
'-Djava.library.path=${ZMQ_LIB_PATH}']
In the generated start scripts I see:
DEFAULT_JVM_OPTS='"\$DEBUG_OPTS" "-Djava.library.path=\${ZMQ_LIB_PATH}"'
I don't want the \$ in there. I tried using '$$DEBUG_OPTS' and also '\$DEBUG_OPTS' but got the same result. What is the right way to escape the $ so it ends up in the script without a backslash in front of it?
I had a similar issue, trying to add a commandline parameter $1 in there. With some googling came up with this solution, fixing the script after the fact.
applicationDefaultJvmArgs=['-Dmy.property=DOLLARONE']
...
startScripts{
doLast{
def bashFile = new File(getOutputDir(),applicationName)
String bashContent = bashFile.text
bashFile.text = bashContent.replaceFirst('DOLLARONE', Matcher.quoteReplacement('$1'))
}
}
The StartScriptGenerator code implies that '$' will be unconditionally replaced by the '\$'.
I assume that your intention is to use '$' character for shell parameters extension but I would like to point out that such usage (if permitted by the gradle task that generates the scripts) is not interoperable between bash and bat scripts - in the bash it will be used for shell parameters extension but in the bat it will have no meaning.
For Kotlin build script the solution could look like:
tasks.named<CreateStartScripts>("startScripts") {
doLast {
unixScript.writeText(unixScript.readText().replace("{{APP_HOME}}", "\${APP_HOME}"))
windowsScript.writeText(windowsScript.readText().replace("{{APP_HOME}}", "%APP_HOME%"))
}
}

How do you create a Bash function that accepts files of a specific type as arguments?

So far, I know that you have to create a function in order to pass arguments.
However, how do you denote the type of the argument?
For instance, if you want to compile a Java class file and then run the resulting Java file (without having to type the file name twice to distinguish between the extensions each time), how do you let the function know that the names belong to files of different types?
Let's say this is our function:
compileAndRun()
{
javac $1
java $2 # basically, we want to make this take the same argument
# (because the names of the *.class and *.java files are the same)
}
So, instead of typing:
compileAndRun test.class test.java
We wanna just type this:
compileAndRun test
Any help along with any extraneous information you wanna throw in would be much appreciated.
Just use $1 twice. It is safer to connect the two commands with &&, so java is not run if the compilation is not successful.
function compile_n_run () {
javac "$1".java && java "$1".class
}
Arguments to bash functions don't really have types; they are just strings, and it's up to you to use them appropriately. In this case, it's fairly simply to write a function which takes a Java source file, compiles it, and runs the resulting output.
compile_n_run () {
source=$1
expected_output="${source%.java}.class"
javac "$source" && java "$expected_output"
}
$ compile_n_run test.java
I chose to require the full Java source name because it's a little friendlier with auto-completion; you don't have to remove the .java from the command-line, rather you let the function do that for you. (And otherwise, this answer would be identical to choroba's).

Resources