tags:

views:

62

answers:

2

I am trying to run "tar -ztf /users/home/test.tar.gz | head -1" in Java, which worked when I tried to run it in unix command line directly.
The result of this command will list one line of the file/folder inside of the test.tar.gz. for example: proj/test/test_dir
But I when I run it in java. it will give this error:

Running command: tar -ztf /users/home/test.tar.gz | head -1
     [java] tar: Options `-[0-7][lmh]' not supported by *this* tar
     [java] Try `tar --help' for more information.

Any idea what's wrong with it? why is it related to "specify drive and density" option?

The code I have run:

 String s = null;
 StringBuffer sbOutput = new StringBuffer();
  StringBuffer errorInfo = new StringBuffer();
  String[] cmd = {"tar", "-ztf", fileName, "|", "head", "-1"};
  try
     {
      Runtime rt = Runtime.getRuntime();
      System.out.println("Running command: " + cmd[0] + " " + cmd[1] + " " + cmd[2] + " " + cmd[3] + " " + cmd[4] + " " + cmd[5]);
        Process p = rt.exec(cmd);            

        BufferedReader stdInput = new BufferedReader(new InputStreamReader(p.getInputStream()));
        BufferedReader stdError = new BufferedReader(new InputStreamReader(p.getErrorStream()));      

        //If there is an error - only show that
        while ((s = stdError.readLine()) != null)
        {
            errorInfo.append(s + "\n");
        }
        if (errorInfo.length() > 0)
        {
         System.out.println(errorInfo.toString());            
        }

        while ((s = stdInput.readLine()) != null) {
         sbOutput.append(s + "\n");
        }


  // wait for end of command execution
  try {
   p.waitFor();
  } catch (InterruptedException ie) {            
   new LogErrThread(ie).start();
   ie.printStackTrace();
     } 

        p.destroy();

        if (sbOutput.length() > 0)
        {
         System.out.println(sbOutput.toString()); 


        }

 }
    catch (IOException e)
    {            
     new LogErrThread(e).start();
  e.printStackTrace();
    }
+2  A: 

On the command line, the shell is doing the piping for you. Only the arguments before the | are passed to gtar. Your code incorrectly passes the pipe and the rest of the text as arguments to gtar.

Luckily, the solution is simple. You can simply read the first line yourself.

String[] cmd = {"gtar", "-ztf", fileName};

// ...

// Instead of current input loop.
s = stdInput.readLine();
if(s != null) {
    sbOutput.append(s + "\n");
}

while (stdInput.readLine() != null) {
    // Disregard.  Reading to end to prevent hang.
}
Matthew Flaschen
I guessed that it's the pipe causing the problem. I will try your solution tomorrow and give the feed back then. Thanks a lot everyone!
mengmenger
got it working by remove the pipe part. It just need to create another thread to get std output when the file list is very long, otherwise the program will hang. thanks again!
mengmenger
+2  A: 

To elaborate Matthew's point, the | operator is interpreted by the shell. To run your command without the shell, you would need to launch the programs separately and connect their pipes together (tricky in Java).

If you input is sanitized, you can invoke the shell and give it the command to run. Its the easier approach, though arguably less portable. In general, the SHELL environment variable contains the user's shell. Shells also have a defacto standardized -c option to pass them a command string in argv. If you invoke $SHELL -c [command string], you should get the behavior you want.

Yann Ramin
for your information, I can also user "$SHELL -c tar -ztf <tar ball file> | head -1" as a command which runs in Java? I didn't find much information about this online. could you please give a bit more infor?thanks a lot!
mengmenger