Including all the jars in a directory within the Java classpath
Solution 1
Using Java 6 or later, the classpath option supports wildcards. Note the following:
- Use straight quotes (
"
) - Use
*
, not*.jar
Windows
java -cp "Test.jar;lib/*" my.package.MainClass
Unix
java -cp "Test.jar:lib/*" my.package.MainClass
This is similar to Windows, but uses :
instead of ;
. If you cannot use wildcards, bash
allows the following syntax (where lib
is the directory containing all the Java archive files):
java -cp "$(printf %s: lib/*.jar)"
(Note that using a classpath is incompatible with the -jar
option. See also: Execute jar file with multiple classpath libraries from command prompt)
Understanding Wildcards
From the Classpath document:
Class path entries can contain the basename wildcard character
*
, which is considered equivalent to specifying a list of all the files in the directory with the extension.jar
or.JAR
. For example, the class path entryfoo/*
specifies all JAR files in the directory named foo. A classpath entry consisting simply of*
expands to a list of all the jar files in the current directory.A class path entry that contains
*
will not match class files. To match both classes and JAR files in a single directory foo, use eitherfoo;foo/*
orfoo/*;foo
. The order chosen determines whether the classes and resources infoo
are loaded before JAR files infoo
, or vice versa.Subdirectories are not searched recursively. For example,
foo/*
looks for JAR files only infoo
, not infoo/bar
,foo/baz
, etc.The order in which the JAR files in a directory are enumerated in the expanded class path is not specified and may vary from platform to platform and even from moment to moment on the same machine. A well-constructed application should not depend upon any particular order. If a specific order is required then the JAR files can be enumerated explicitly in the class path.
Expansion of wildcards is done early, prior to the invocation of a program's main method, rather than late, during the class-loading process itself. Each element of the input class path containing a wildcard is replaced by the (possibly empty) sequence of elements generated by enumerating the JAR files in the named directory. For example, if the directory
foo
containsa.jar
,b.jar
, andc.jar
, then the class pathfoo/*
is expanded intofoo/a.jar;foo/b.jar;foo/c.jar
, and that string would be the value of the system propertyjava.class.path
.The
CLASSPATH
environment variable is not treated any differently from the-classpath
(or-cp
) command-line option. That is, wildcards are honored in all these cases. However, class path wildcards are not honored in theClass-Path jar-manifest
header.
Note: due to a known bug in java 8, the windows examples must use a backslash preceding entries with a trailing asterisk: https://bugs.openjdk.java.net/browse/JDK-8131329
Solution 2
Under Windows this works:
java -cp "Test.jar;lib/*" my.package.MainClass
and this does not work:
java -cp "Test.jar;lib/*.jar" my.package.MainClass
Notice the *.jar
, so the * wildcard should be used alone.
On Linux, the following works:
java -cp "Test.jar:lib/*" my.package.MainClass
The separators are colons instead of semicolons.
Solution 3
We get around this problem by deploying a main jar file myapp.jar
which contains a manifest (Manifest.mf
) file specifying a classpath with the other required jars, which are then deployed alongside it. In this case, you only need to declare java -jar myapp.jar
when running the code.
So if you deploy the main jar
into some directory, and then put the dependent jars into a lib
folder beneath that, the manifest looks like:
Manifest-Version: 1.0
Implementation-Title: myapp
Implementation-Version: 1.0.1
Class-Path: lib/dep1.jar lib/dep2.jar
NB: this is platform-independent - we can use the same jars to launch on a UNIX server or on a Windows PC.
Solution 4
My solution on Ubuntu 10.04 using java-sun 1.6.0_24 having all jars in "lib" directory:
java -cp .:lib/* my.main.Class
If this fails, the following command should work (prints out all *.jars in lib directory to the classpath param)
java -cp $(for i in lib/*.jar ; do echo -n $i: ; done). my.main.Class
Solution 5
Short answer: java -classpath lib/*:. my.package.Program
Oracle provides documentation on using wildcards in classpaths here for Java 6 and here for Java 7, under the section heading Understanding class path wildcards. (As I write this, the two pages contain the same information.) Here's a summary of the highlights:
In general, to include all of the JARs in a given directory, you can use the wildcard
*
(not*.jar
).The wildcard only matches JARs, not class files; to get all classes in a directory, just end the classpath entry at the directory name.
The above two options can be combined to include all JAR and class files in a directory, and the usual classpath precedence rules apply. E.g.
-cp /classes;/jars/*
The wildcard will not search for JARs in subdirectories.
The above bullet points are true if you use the
CLASSPATH
system property or the-cp
or-classpath
command line flags. However, if you use theClass-Path
JAR manifest header (as you might do with an ant build file), wildcards will not be honored.
Yes, my first link is the same one provided in the top-scoring answer (which I have no hope of overtaking), but that answer doesn't provide much explanation beyond the link. Since that sort of behavior is discouraged on Stack Overflow these days, I thought I'd expand on it.
Bulki
Recent computer science graduate working as a programmer analyst.
Updated on July 13, 2022Comments
-
Bulki almost 2 years
Is there a way to include all the jar files within a directory in the classpath?
I'm trying
java -classpath lib/*.jar:. my.package.Program
and it is not able to find class files that are certainly in those jars. Do I need to add each jar file to the classpath separately?-
Bulki about 13 yearsSorry I've never accepted this. It should be a community wiki. Never used one of the provided answers. I believe I created a shell script that just scanned the lib/ directory and created the classpath from parsing file names.
-
Alex R about 13 yearsThere's some kind of bug in this new Java feature, because it does not work as described. I gave up and used Ant to work around it, as described in one of the answers.
-
Mike almost 12 yearsThere is issue with wildcard processing in Windows. stackoverflow.com/questions/11607873/…
-
KNU over 9 yearsAt first I thought the
.
afterjar:
is put by mistake but..... The standard symbol for `current directory' is a single period (.) in both Unix and Windows systems. -
Evgeni Sergeev over 9 yearsShort answer: (1) drop the
.jar
part, (2) must have at least 2 parts, separated by a;
on Windows (which is usually:
elsewhere). For example:java -classpath ".;lib/*" Program
-
Sagar Kharab almost 3 yearsReally sorry but since this is a popular question and I can't ask my own question, I am seeking Java Expert Answer for what is the difference between the flag create vs create new at here github.com/frohoff/jdk8u-jdk/blob/master/src/solaris/classes/…
-
-
Giovanni Funchal almost 14 yearsThis works, but watch out, pass the
-Djava.ext.dirs=
BEFORE-jar
-
Tom over 13 yearsAwesome. Something like this works for me:java -cp target/classes;target/lib/* de.byteconsult.Main
-
Cristopher Van Paul over 13 yearsjava.ext.dirs will work very different from a normal jar in classpath. It has higher priority and permission which will able to somehow override classes in bootstamp(rt.jar)
-
Alex R about 13 yearsThe feature is poorly documented, and seems to require some less-than-obvious pre-conditions to be satisfied in order to work as intended.
-
Raku over 12 yearsThis seems to work for a lot of people, however, Java seems to plainly ignore the Class-Path entries in the manifest file here. We cannot run the application without manually adding "lib/*" to the classpath using -cp. Any ideas?
-
albfan about 12 yearsa funny note. java -cp lib/* my.main.Class will fail always because shell glob expansion of lib/*, while java -cp .:lib/* my.main.Class will not because .:lib/* is not a valid glob path. Take a while to note that
-
Ellen Spertus almost 12 yearsLord Torgamus below provides an example and explanation.
-
JohnnyLambada almost 12 yearsYou can also use find:
cp=$(find /path/to/std/jars /path/to/your/jar -not -type d -printf "%p:")
-
Eyad Ebrahim over 11 yearsmy problem was with lib/*.jar rather than lib/*. Thanks a lot this fixed it. I noticed that there's a difference between : and ; but that could be my testing-many-changes-at-the-same-time kind of thing.
-
Wim Deblauwe over 11 yearsThe perfect answer. 2 important things to notice: 1) Use quotes and 2) Use * only, not *.jar
-
rzwitserloot over 11 yearsoxbow_lakes's answer isn't entirely correct; the Class-Path thing is honored (and ONLY that is honored; -cp/-classpath is ignored!) if you start this jar with java -jar myapp.jar. I presume oxbow_lakes meant to write that when he wrote 'java -classpath myapp.jar'.
-
rzwitserloot over 11 yearsThis does not work; linux will expand the . you can try: java -cp '.:lib/' and that works fine (note the single quotes! It won't work with double quotes!). Actually, .:lib/* might work if that's not a legit glob due to the colon, but it feels a bit iffy. I'd add the quotes. The single quotes tell bash to not touch any part of the contents.
-
Supr about 11 years+1 for the last bash/tr trick. Java/JamVM here doesn't like wildcards for paths outside the working directory, but explicitly referencing each JAR using shell wildcard +
tr
works! -
jamesmortensen over 10 yearsA year and 8 months later, the edit I made to include the UNIX version saved me yet again. :) Funny how it wouldn't recognize my jar files with
*.jar
but only with*
. -
yellavon about 10 yearsI have a command
java -classpath /jars/*:/anotherJarsDir/* com.test.MyClass
without any quotes and it works fine. I'm wondering why shell isn't expanding it and erroring out? -
user13107 about 10 yearsI found that the order of classpaths is important (but I don't know why). I was getting errors until I switched order of classpaths.
-
Sebastian about 10 years@jmort253, the thing is, this is not the shell * expanding, but the wildcard is java parsing the classpath, seeing the * and filling in the wildcard
-
jamesmortensen about 10 years@SebastianGodelet - Yeh, that's just me getting confused between Regex wildcards and this notation, which isn't the same I guess. Mostly, what saved me is knowing the difference between
:
on one platform and;
on the other. :) I compile with Java from the command line about once per year, just enough not to remember how yet often enough to be annoying. -
simo.3792 over 9 yearsThis may have been the only way back in '08, but not anymore.
-
simo.3792 over 9 yearsThis may have been the only way back in '08, but not anymore.
-
AndiDog about 9 yearsMind that
java -cp "Test.jar;lib/*" my.package.MainClass
works but if the classpath parameter is given as second argument, it does not work (java my.package.MainClass -cp "Test.jar;lib/*"
). -
Devon Peticolas about 9 yearsThis isn't the worst thing. It's a hack, but I have this set in my bashrc
for jar in $(ls $HOME/bin/*.jar); do export CLASSPATH=$jar:$CLASSPATH; done
-
Sohail Si almost 9 yearsAlso don't use
~
in the -cp -
Angel O'Sphere almost 8 yearsIt does not matter (in this context) if you use single or double quotes. You want to prevent the shell from expanding (globbing) the *, that is all. And pass the text "lib/*" litterally to the JVM, so the VM recognices this as a "special pattern" and searches by itself for jar files.
-
manifold almost 8 yearsFollowing is not valid as well java -cp = " " like you use in set classpath=" "
-
Konstantin Pelepelin about 6 yearsSingle quotes should be used in bash
-
philwalk almost 6 yearsYour windows example doesn't work with java 8 or earlier, but would with this classpath: Test.jar;lib\* ... forward slash is okay except when preceding an asterisk and a few others ... see bugs.openjdk.java.net/browse/JDK-8131329
-
philwalk almost 6 yearswindows example doesn't work for java 8 and earlier: see bugs.openjdk.java.net/browse/JDK-8131329
-
Wender almost 6 yearsMaybe does not work for open JDK, I will test this and I will talk about here
-
philwalk almost 6 yearswindows example seems to have worked for java 6, maybe java 7, but not for java 8 (see bugs.openjdk.java.net/browse/JDK-8131329)
-
burak almost 6 yearsThanks for the emphasising the difference between * and *.jar
-
Wender over 5 yearsSorry, I did test with HotSpot and I did think that works with openjdk.
-
philwalk over 5 yearsOracle java under windows requires a backslash prior to the asterisk rather than a forward slash, although I haven't re-tested the most recent or alternate java versions.
-
Jonathan Drapeau over 5 yearsWorks for java 8 in linux
-
Peter almost 5 yearsIn Cygwin we need to use semicolon (
;
) separator instead of colon (:
) -
Matt Campbell over 4 yearsThanks. On 'java version "1.8.0_221" Java(TM) SE Runtime Environment (build 1.8.0_221-b27) Java HotSpot(TM) 64-Bit Server VM (build 25.221-b27, mixed mode)', only this -D version of passing in the classpath worked. The traditional form did not.
-
Anish B. over 4 years@basszero With double quotes, It worked on MacOS 10.15.2 Catalina. Thanks :) +1 for this.
-
Aman about 4 yearswhat about older version than java 6 @basszero
-
Mugeesh Husain almost 4 yearsjava -classpath "lib/*:." my.package.Program is worked for me
-
Datbates almost 4 yearsI am not sure why having the additional classpath entry for "." fixed my problem, but it works now. "." is the same directory as the directory I specified with the wildcard. I can't see why this would matter, but it did. Thanks!
-
Hardik Rana over 3 yearsjava -cp "Test.jar;lib/*" my.package.MainClass will this not look for children folders under lib? Eg my jar is in directory lib/org/abc.jar
-
Hardik Rana over 3 yearsjava -cp "Test.jar;lib/*" my.package.MainClass will this not look for children folders under lib? Eg my jar is in directory lib/org/abc.ja
-
Hardik Rana over 3 yearsjava -cp "Test.jar;lib/*" my.package.MainClass will this not look for children folders under lib? Eg my jar is in directory lib/org/abc.ja
-
Hardik Rana over 3 yearsjava -cp "Test.jar;lib/*" my.package.MainClass will this not look for children folders under lib? Eg my jar is in directory lib/org/abc.ja
-
Sridhar Sarnobat over 2 yearsI may no longer need groovy!
-classpath ~/".groovy/lib/*"