title: Java, Runtime.exec or ProcessBuilder: how to know if the file is shell or binary?
body: <p><strong>I'm looking into a most efficient way to decide:</strong></p>
  
  <ul>
  <li>Should I preprend the user-provided command line with the shell executable</li>
  <li>If yes, what would that executable be? (/bin/sh? /usr/bin/perl? /usr/bin/ksh? c:/../cmd.exe?)</li>
  </ul>
  
  <p>It is known that to start a shell script from Java one should start the shell instead:</p>
  
  <pre><code>ProcessBuilder pb = new ProcessBuilder("/bin/sh", "script.sh", "arg1", "arg2);
  </code></pre>
  
  <p>To start a binary one should start the binary itself:</p>
  
  <pre><code>ProcessBuilder pb = new ProcessBuilder("/path/binary", "arg1", "arg2);
  </code></pre>
  
  <p>If a binary is executed with shell, it produces an error:</p>
  
  <pre><code>ProcessBuilder pb = new ProcessBuilder("/bin/sh", "/path/binary", "arg1", "arg2);
  (sh: cannot execute binary file)
  </code></pre>
  
  <p>If a shell script is executed without the shell binary, it produces an error:</p>
  
  <pre><code>ProcessBuilder pb = new ProcessBuilder("script.sh", "arg1", "arg2);
  (error 2: file not found)
  </code></pre>
  
  <p>I'm in a situation where my application doesn't know what it starts, binary or a script. </p>
  
  <p>The started application is a event handler provided <strong>by the end user</strong>. It most likely be a shell script executed under Unix; but it can be a *.cmd under Windows, or a Perl script executed under some obscure platform. It is Java, after all.</p>
  
  <p>My first naive attempt was to start the command line with the shell, and see if it works. If not, try to execute it as a binary. </p>
  
  <p>This is ugly and risky: under some unknown combination of platform and shell the second ran may still execute the script, second time, with unpredictable results.</p>
  
  <p>Also, I cannot tell when the script started OK and failed due to some issue of its own from when I just cannot start it.</p>
  
  <p><strong>The best thing I'm considering now is:</strong></p>
  
  <ul>
  <li>Read the script and look for any unprintable bytes</li>
  <li>If found, consider it a binary</li>
  <li>If not, add /bin/sh (or cmd.exe if under Windows)</li>
  </ul>
  
  <p>Please advise if you have any better ideas in mind.</p>
  
  <p><strong>UPDATE/PARTIAL SOLUTION</strong></p>
  
  <p>Thanks to everyone who shared their thoughts with me.</p>
  
  <p>Turns out, I have confused myself and the rest of the Internet :)</p>
  
  <p>It is not required to prepend the shall binary before the user-entered command line providing that:</p>
  
  <ol>
  <li>the script is in PATH</li>
  <li>(for Unix) the script is executable</li>
  <li>(for Unix) the script has #!/path/to/interpreter</li>
  </ol>
  
  <p>While I was testing my code, one or another of these conditions did not met. :-(</p>
  
  <p>After performing the test carefully from the scratch script has been executed.</p>
  
  <p>Point 3 is only can be done by the user, and have to be documented in User Manual.</p>
  
  <p>Due to the way these scripts are propagated to the target system, they may be not executable and may not be in PATH. </p>
  
  <p>The only path I care about is relative one, so it is enough to prepend a ./ to any relative path.</p>
  
  <p>Making the scripts executable under Unix (and any other platform) is a more of a challenge. It is not WORA. Placing /bin/sh in front of it may help, but if I remember right under Solaris the shell will not execute a non-executable script. </p>
  
  <p>I'll post another update later this week.</p>