5

I need to run a java command with a custom classpath.

On Windows I need to type:

java -cp foo;bar

On Linux I need to type:

java -cp foo:bar

We currently have a .bat file containing the first version and a .sh file containing the second version. This works fine most of the time, but fails for git-bash on Windows, which needs a shell script with a semicolon delimiter.

Is there any system independent way to write such a classpath?

I would think of something like

java -cp foo -cp bar

but this does not this way.

Currently the only way I see is having some shell logic determining the OS and generating the correct command line from that.

Is there an easier way to do this the java way?

michas
  • 25,361
  • 15
  • 76
  • 121
  • How you can run a shell script under windows? – Jens Aug 29 '14 at 08:11
  • Yes, bash is available for windows, too. For example if you install git, it contains a really nice shell: git-bash. – michas Aug 29 '14 at 08:12
  • 2
    Not that I'm aware of. The closest thing that comes to mind is to put the classpath information in a manifest and package it in a jar. – aioobe Aug 29 '14 at 08:14

2 Answers2

4
  • Option 1: If you don't mind creating a jar before running, you could specify the classpath in a manifest file. Those paths are space-separated. (See Adding Classes to the JAR File's Classpath)

  • Option 2 Add code for detecting OS using for instance uname. Then do either SEP=\; or SEP=: and use path${SEP}path. (See for instance How to check if running in Cygwin, Mac or Linux?)

  • Option 3: Grep the java help output to see what separator character java expects:

    SEP=$(java -h |& grep "A [:;] separated" | grep -o "[:;]")
    
  • Option 4: If you have the JDK installed, you can print the File.pathSeparator:

    echo "interface C { static void main(String[] a) { System.out.print(java.io.File.pathSeparator); }}" > C.java
    javac C.java
    java C
    rm C.{java,class}
    

Note: Only the path separators, i.e. ; vs :, are platform specific. Forward slashes (i.e. some/class/path) work fine on all systems for separating directories.

aioobe
  • 413,195
  • 112
  • 811
  • 826
  • 1
    Current option 3 (`SEP=$(java -h |& grep "A [:;] separated" | grep -o "[:;]")`) only works for an English locale. Here is my take (successfully tested on German *Windows 7* and English *Ubuntu 14.04 LTS*): `SEP=$( [ $(java -h |& grep ";" | wc -l ) == 1 ] && echo ";" || echo ":" )` – Abdull Apr 22 '16 at 14:10
  • Option 3 must be a joke. – 0xF Nov 21 '17 at 21:17
  • @0xF, it's a bit hacky, but if you think of it, the `java` command on the running system is the single source of truth for what separator symbol `java` accepts. The `java -h` happens to print the correct symbol. Added a fourth option which is perhaps less hacky, but requires the JDK. – aioobe Nov 21 '17 at 21:51
2

Don't specify it at all. Use the 'java -jar' command, naming a JAR file with a Manifest.MF containing a Main-Class attribute, and if necessary a Class-Path attribute, specifying the relative locations of any other JARs this one depends on. As this is done via space-separated relative URLs, it is automatically system-independent.

user207421
  • 305,947
  • 44
  • 307
  • 483
  • *As this is done via relative URLs, it is automatically system-independent.* -- Seems to indicate that you believe that the *paths* that are problematic. Java accepts class paths with `/` both on Windows and *nix. It's the *path separators* that are platform specific. – aioobe Aug 29 '14 at 10:03
  • Does the Class-Path attribute allow the use of wildcards like `lib/*`? (A quick test did not work.) The paths in the classpath are relative to the current working directory, right? – michas Aug 29 '14 at 10:04
  • No, class path wild cards are not supported in manifest files. See http://docs.oracle.com/javase/6/docs/technotes/tools/windows/classpath.html : *However, class path wildcards are not honored in the Class-Path jar-manifest header.* They are supported when provided on the class path though. – aioobe Aug 29 '14 at 10:06
  • @aiiobe No, I believe the paths may be *part* of the problem. The OP indicates that the path separator is his main problem. – user207421 Aug 29 '14 at 10:24
  • 1
    @michas I don't see why you need a wildcard. You know the required JAR files in advance, and you have to distribute them with your application. Wildcard *ergo* not required. – user207421 Aug 29 '14 at 10:26
  • I was able to solve my problem the maven way: http://maven.apache.org/shared/maven-archiver/examples/classpath.html Maven generates the correct Manifest entries and I can simply use 'java -jar'. – michas Aug 29 '14 at 12:06
  • in the Class-Path entry in the manifest, the folder separators are platform specific, java was not able to resolve path with / in windows and when I changed the manifest and replaced / with \ it worked. Is there a way to avoid this ? – SeB.Fr Jun 08 '17 at 13:09