39

I want to distribute a command-line application written in Java on Windows.

My application is distributed as a zip file, which has a lib directory entry which has the .jar files needed for invoking my main class. Currently, for Unix environments, I have a shell script which invokes the java command with a CLASSPATH created by appending all files in lib directory.

How do I write a .BAT file with similar functionality? What is the equivalent of find Unix command in Windows world?

10 Answers 10

65

You want to use the for loop in Batch script

 @echo off
 setLocal EnableDelayedExpansion
 set CLASSPATH="
 for /R ./lib %%a in (*.jar) do (
   set CLASSPATH=!CLASSPATH!;%%a
 )
 set CLASSPATH=!CLASSPATH!"
 echo !CLASSPATH!

This really helped me when I was looking for a batch script to iterate through all the files in a directory, it's about deleting files but it's very useful.

One-line batch script to delete empty directories

To be honest, use Jon's answer though, far better if all the files are in one directory, this might help you out at another time though.

Sign up to request clarification or add additional context in comments.

4 Comments

+1 since it's the only one that answered the specific question.
You really did my day. Thanks for such a on to the point reply
if using a pushd/popd then need to "endLocal" before the popd.
did not work for me, and also very complex to understand
29

Why would you use find? Presumably you know all the libraries your jar file needs ahead of time, so why not just list them?

Alternatively, you could always use -Djava.ext.dirs=lib and let it pick up everything that way.

6 Comments

Jon, I wasn't aware of the java.ext.dirs system property - thanks! Imagine an application where you want the user to drop the driver jar in the lib directory, edit a property file and connect to a database using JDBC - my application is similar, and I do not know the CLASSPATH ahead of time.
@binil: Yes, that makes sense. It was just your description in the question which made it sound like all the files you needed were in the zip file.
Changing -Djava.ext.dirs is problematic. For example, when I try and use -Djava.ext.dirs, SSL certificate validation breaks.
@KannanGoundan: You should be able to include your previous extension directory in that path as well.
@JonSkeet: I'm trying to write a launcher script to distribute with my program. Is there an easy way to figure out what my previous extension directory is?
|
18

Since 6.0, Java supports wildcard classpaths.

Java command-line classpath syntax

2 Comments

Thanks, I was not aware of this feature! But my target environment is Java5, so I might not be able to use this technique in this application.
However it's not supported in Manifest.MF unfortunately
5

A variation if you want the CLASSPATH setting to hold outside of the script and you didn't start the shell with /V, you can do something like this:

@echo off
FOR /R ./lib %%a in (*.jar) DO CALL :AddToPath %%a
ECHO %CLASSPATH%
GOTO :EOF

:AddToPath
SET CLASSPATH=%1;%CLASSPATH%
GOTO :EOF

Useful for setting up your environment when you are just playing around on the command line.

Comments

4

Sounds like an executable JAR could work for you. If you're distributing a ZIP with all the JARs your main routine needs, and you really execute it in a command shell, perhaps you could create an executable JAR with the Main-Class and Classpath defined in the manifest. All your users have to do is double click on the JAR and Bob's your uncle.

1 Comment

Yes, thanks for reminding me of this option! I think I consider should executable JARs with an appropriate manifest entry.
2
SET CLASSPATH=""
FOR /R /lib %%a in (*.jar) DO CALL :AddToPath %%a
echo %CLASSPATH%

java -cp %CLASSPATH% com.a.b.MyClass

pause

:AddToPath
SET CLASSPATH=%1;%CLASSPATH%
GOTO :EOF

Comments

0

What I do when I release command-line JARs for Windows/Linux is to embed all the JAR libraries inside my JAR using the ANT command:

       <fileset dir="${module.classes.dir}"/>
       <zipfileset src="${endorsed.lib.dir}/myLibrary.jar"/>

In this way the libraries are melt together with your class files.

It is not the best way of binary reusability, but if the libraries are not so heavy, you have your application executed by simply calling java -jar myApp.jar in any OS.

1 Comment

I (think I) cannot use this "uberjar" idea because I use two spring jars, which embed different XML schema definitions in entries with the same name, which I might need to merge by hand and would be an extra build step.
0

You may use a bit different way if you use Maven to build your project. Application Assembler Maven Plugin is intended for creating Java apps launchers. This plug-in generate bat file launcher for you and put dependencies in specified folder. Optionally you launcher is able to register you application as a service\demon.

This is a topic about using it

This plug-in helps keeping you CM parts of your project DRY.

Comments

0

Is there an easier way to do this?

Yes;

Since version 6, you can use class path wildcards.

javac -cp .;../lib/* yourJavaCodeDir/YourJavaFile.java

See also this related Q&A.

Comments

0

An option to make things portable is to set the classpath relative to the location of the batch file itself.

In Windows (assuming Java 6+, classes in ./bin, jars in ./lib):

@java -classpath %~dp0/bin;%~dp0/lib/* ClassName %1

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.