How can I detect a Unix-like OS in Java?
Ok, I know that System.getProperty("os.name")
will give me the name of the OS I'm running under, but that's not a lot of help. What I need to know is if the OS I'm running on is a 'Unix-like' OS, I don't care if it's HP-UX, AIX, Mac OS X or whatever.
From the list of possible os.name values it seems like a quick and dirty way of detecting a 'Unix-like' OS is checking if os.name
does not contain "Windows". The false positives that will give me are OSes my code is very unlikely to encounter! Still, I'd love to know a better way if there is one.
Use the org.apache.commons.lang.SystemUtils
utility class from Commons Lang, it has a nice IS_OS_UNIX
constant. From the javadoc:
Is
true
if this is a POSIX compilant system, as in any of AIX, HP-UX, Irix, Linux, MacOSX, Solaris or SUN OS.The field will return false if OS_NAME is null.
And the test becomes:
if (SystemUtils.IS_OS_UNIX) {
...
}
Simple, effective, easy to read, no cryptic tricks.
I've used your scheme in production code on Windows XP, Vista, Win7, Mac OS 10.3 - 10.6 and a variety of Linux distros without an issue:
if (System.getProperty("os.name").startsWith("Windows")) {
// includes: Windows 2000, Windows 95, Windows 98, Windows NT, Windows Vista, Windows XP
} else {
// everything else
}
Essentially, detect Unix-like by not detecting Windows.
File.listRoots()
will give you an array of the file system root directories.
If you are on a Unix-like system, then the array should contain a single entry "/"
and on Windows systems you'll get something like ["C:", "D:", ...]
Edit: @chris_l: I totally forgot about mobile phones. Some digging turns up that Android returns a "/\0\0"
- a slash followed by two null bytes (assumed to be a bug). Looks like we avoid false positives for the time being through luck and coincidence. Couldn't find good data on other phones, unfortunately.
It's probably not a good idea to run the same code on desktops and mobile phones regardless, but it is interesting to know. Looks like it comes down to needing to check for specific features instead of simply the system type.
Javadoc says: On UNIX systems the value of this
* field is '/'
; on Microsoft Windows systems it is '\'
.
System.out.println( File.separatorChar == '/' ? "Unix" : "Windows" );
System.getProperty("os.name");
is about the best you are going to get.
I agree with @Fuzzy in that I think the only way that Java intended you to be able to get that information was through the os.name
property.
The only other things I can think of are:
Have a shell script or batch file wrapper to launch your Java app that passes in OS information using the
-D
argument to the JVM. Though given your description, this doesn't sound doable.You could try to check for the existence of an OS-specific directory. For instance, you could assume the directory
"/"
will always exist on a Unix-like system, but not on Windows and do something like this:if((new File("/")).exists()) { System.out.println("I'm on a Unix system!"); }
Try to kick off a Unix-specific command line command like
ls
and check the return code. If it worked, you're on a Unix-like system, if not you're on Windows.
All of those solutions are really just hacks though and frankly I don't really feel all that great about any of them. You're unfortunately probably best off with your original thought. Fun, eh?
Use File.pathSeparator or File.separator. The first will return ";" in Windows and ":" in Unix. The second will return "\" in Windows and "/" in Unix.
You could try to execute the uname
command - should be available on all unixoid systems.
package com.appspot.x19290;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
public class UnixCheck {
public static void main(String[] args) {
UnixCheck s = UnixCheck.S;
String isUnix = s.unix ? "is Unix" : "not Unix";
try {
System.out.println(isUnix + ", devnull: " + s.devnull.getPath());
} catch (NullPointerException e) {
System.out.println(isUnix + ", devnull: unknown");
}
}
public static final UnixCheck S = new UnixCheck();
public static final UnixCheck TEST = new UnixCheck(true);
public final boolean unix;
public final File devnull;
private UnixCheck() {
this(false);
}
private UnixCheck(boolean testing) {
String path;
path = testing ? "/<dev>/<no><such><null><device>" : "/dev/null";
File devnull = devnullOrNone(path);
if (devnull == null) {
this.unix = false;
path = testing ? "<no><such><null><device>" : "nul";
this.devnull = devnullOrNone(path);
} else {
this.unix = true;
this.devnull = devnull;
}
}
private static File devnullOrNone(String name) {
File file = new File(name);
if (file.isFile())
return null;
if (file.isDirectory())
return null;
try {
FileInputStream i = new FileInputStream(file);
try {
i.read();
} finally {
i.close();
}
} catch (IOException e) {
return null;
}
return file;
}
}
精彩评论