Including all the jars in a directory within the Java classpath
classpath, command-line, java
Solution
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 entry `foo/*` 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 either `foo;foo/*` or `foo/*;foo`. The order chosen determines whether the classes and resources in `foo` are loaded before JAR files in `foo`, or vice versa.
Subdirectories are not searched recursively. For example, `foo/*` looks for JAR files only in `foo`, not in `foo/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` contains `a.jar`, `b.jar`, and `c.jar`, then the class path `foo/*` is expanded into `foo/a.jar;foo/b.jar;foo/c.jar`, and that string would be the value of the system property `java.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 the `Class-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
Problem
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?