tags:

views:

339

answers:

10

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.

+5  A: 

System.getProperty("os.name"); is about the best you are going to get.

fuzzy lollipop
A: 

You could try to execute the uname command - should be available on all unixoid systems.

Chris Lercher
+13  A: 

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.

MikeD
I've been writing Java for years and I never noticed that function existed. Nice!
Brent Nash
Very good idea, but I wonder, if there there other non-Windows, non-Unix systems, that have a root "/"?
Chris Lercher
@chris_l: Most non-Windows, non-Unix systems are built as research projects for a specific purpose and a specific language, like Amoeba (Python) and House (Haskell). It feels like a cop-out answer, but I'm going to venture a guess that most of them don't have a built Java VM. That caveat aside, I would have to agree with David Thornlay's comment on the question w.r.t. testing for a particular feature rather than simply being Unix-like.
MikeD
@MikeD: I'm thinking more about mobile phones that support Java - and I'm not sure, what their system root is.
Chris Lercher
+1  A: 

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:

  1. 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.

  2. 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!"); }

  3. 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?

Brent Nash
Unfortunately your #2 solution doesn't work. Java will still return "I'm on a Unix system!" even on Windows.
ferrari fan
Yuck. Thanks for the heads up @Ferrari.
Brent Nash
+2  A: 

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.

unhillbilly
Despite the many good ideas posted (I particularly liked File.listRoots) I think this is the "correct" way to do it. False positives are highly unlikely.
mluisbrown
+5  A: 

Javadoc says: On UNIX systems the value of this * field is '/'; on Microsoft Windows systems it is '\'.

System.out.println( File.separatorChar == '/' ? "Unix" : "Windows" );
stacker
Just as effective and more efficient than listRoots
sje397
I do this all the time. It seems rather lame, there should be something more definitive, but it works.
Jay
What about the Classic (pre-OSX) Macintosh, where the separator character was a ':' ?
Steven Schlansker
@Steven: Is there even a modern JVM for pre-OSX Macintosh?
Jesper
@Jesper: Almost certainly not, but that's not the point. Are you **positive** that there are no other separators in use, and more importantly, that there never will be? Doing things like this is fraught with danger, and you're just going to run into problems down the road.
Steven Schlansker
@Steven - For cases like that - one could look at the line-separator it is only carriage return on mac, linefeed on unix and both on dos/windows.
stacker
+7  A: 

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.

Pascal Thivent
@Anders: First of all, let me underline that we are talking about javadoc here. Did you check the implementation before claiming it's *wrong*? Second, what is *utterly wrong* with the list, what would you add? Last thing, feel free to submit a javadoc patch, patches are often welcome if they can improve something.
Pascal Thivent
@Pascal, Last time I looked there were more then a fair share of different Linux distributions, even the oldest one (Slackware) is not POSIX compliant, honestly I don't believe a single one can claim to be. Neither is quite Solaris nor SUN OS (which really should now be the same), and MacOSX is not POSIX compliant either. And no, I did not check the implementation. I will revise the first comment, hopefully the implementation is better then the documentation.
Anders
@Anders: Thanks for the feedback and clarification, I get your point (and I can agree now, the javadoc is not good).
Pascal Thivent
A: 

Use File.pathSeparator or File.separator. The first will return ";" in Windows and ":" in Unix. The second will return "\" in Windows and "/" in Unix.

Greg Mallett
A: 

Just for the fun of it. You could test System.getProperty("line.separator")...

Martin
+1  A: 

Just as an extra warning, trying specific commands could be unhelpful too (depending on what machines you might end up on) -- uname, ls, etc all work on my Windows machine, because I have MinGW+MSYS installed...

Jonathan