Several years ago, when I was at Citcon, the excellent open-space conference for continuous integration, I met a consultant who made a startling admission: He had just been hired to port a Java application. Of course, I knew right away what he meant: one of those Java EE monsters that you need to move from, let's say, Red Hat JBoss to Oracle WebLogic, or the other way around. I could see him spending days twiddling configuration files, testing for buried dependencies, cleaning up database access code, and attending to a hundred other details. I wished him luck and was about to move along when he said it wasn't Java EE.
Ah, said I, it's one of those miserable debug sessions trying to figure out why old J2ME code doesn't work identically on two handsets. I think I'd prefer the enterprise option, I started to explain. No, he said, it wasn't Java ME either. It was straight, vanilla Java SE.
There was no stopping me. Unflappable, I offered: "You mean like SWT to Swing, or Commons logging to log4j, and I started to gain speed as I ticked off all sorts of like-for-like library swaps. Now amused by the game, he patiently, answered no, no, no. To save me from exhaustion and embarrassment, he finally offered, "We're not changing a single library." "In fact," he continued, "I'm porting a text-based app from Linux to Windows."
With this clarification, I suddenly became uncomfortable wondering whether he was a troll testing to see how far he could run the joke. He then added, "The original developers made lots of calls to the command line and many of those calls had OS-specific syntax or relied on OS-specific functionality. That is what I have to port." Aah!
There is no doubt that the introduction of system commands as strings introduces a high risk of non-portability to any program. When developers expect to internationalize an app, they frequently segregate strings into a property file from which they are read at runtime to obtain precisely this kind of portability. However, this technique is little used for embedded commands. And for many situations, in fact, there might be a better solution: Ant the Java build software in many cases offers a more capable and reliable approach.
If you've used Ant, you know that it executes tasks whose parameters are passed to it in XML. This design, while perhaps cumbersome, has the great benefit of being completely portable. A properly written Ant script will work the same on Linux, Windows, Mac OS, etc., without needing to be tweaked. Calling Ant from within a JVM-based program confers the same portability. I am not here talking about actually running Ant scripts from within Java, but rather calling Ant's own internal APIs and passing them the parameters as part of method calls. This is comparatively easy to do, as it requires only that the Ant JAR file be on the classpath for the program.
The APIs are documented in the Javadoc of the binary distributions. A slightly older version can be found online. It's worked well for me in the past.
For many purposes, you primarily would use Ant's core tasks. These are numerous and contain, among others: file copy, delete, and rename; directory make, copy, delete, rename; zip and unzip, text-based input prompts, calculate file checksums, get a file from a URL, a fix for CR/LF issues, and so on.
Some of the file handling functions were added to Java 7 and would be preferred where there is no fear that the software will need to run on pre-version 7 releases. An additional option is to rely on scripting engines that, since Java 7, have enjoyed good performance. The one most tuned to quick and dirty file handling is surely Groovy, although there are many options to choose from. However, if you use a scripting engine, make sure you choose one that has been tested on Java 8. When Java 8 came out, Oracle changed the way it verified certain bytecodes used principally by scripting languages causing some errors in loading and running the engines. These were quickly fixed, so you want those later, fixed versions.
However, when I'm writing Java, I like my entire application to be in one language (with the exception of tests, where I frequently use Groovy for the convenience it brings to unit, integration, and acceptance tests), rather than Java cum scripting language in one codebase. And I like knowing that my code will run on Java 6 without problems. So, for these purposes, I perform file and directory manipulation through Ant's API. It might be an uncommon use of Ant, but it's an excellent solution.