How to invoke a Linux shell command from Java

前端 未结 3 974
轻奢々
轻奢々 2020-11-22 13:52

I am trying to execute some Linux commands from Java using redirection (>&) and pipes (|). How can Java invoke csh or bash commands?

I

3条回答
  •  借酒劲吻你
    2020-11-22 14:52

    Building on @Tim's example to make a self-contained method:

    import java.io.BufferedReader;
    import java.io.File;
    import java.io.InputStreamReader;
    import java.util.ArrayList;
    
    public class Shell {
    
        /** Returns null if it failed for some reason.
         */
        public static ArrayList command(final String cmdline,
        final String directory) {
            try {
                Process process = 
                    new ProcessBuilder(new String[] {"bash", "-c", cmdline})
                        .redirectErrorStream(true)
                        .directory(new File(directory))
                        .start();
    
                ArrayList output = new ArrayList();
                BufferedReader br = new BufferedReader(
                    new InputStreamReader(process.getInputStream()));
                String line = null;
                while ( (line = br.readLine()) != null )
                    output.add(line);
    
                //There should really be a timeout here.
                if (0 != process.waitFor())
                    return null;
    
                return output;
    
            } catch (Exception e) {
                //Warning: doing this is no good in high quality applications.
                //Instead, present appropriate error messages to the user.
                //But it's perfectly fine for prototyping.
    
                return null;
            }
        }
    
        public static void main(String[] args) {
            test("which bash");
    
            test("find . -type f -printf '%T@\\\\t%p\\\\n' "
                + "| sort -n | cut -f 2- | "
                + "sed -e 's/ /\\\\\\\\ /g' | xargs ls -halt");
    
        }
    
        static void test(String cmdline) {
            ArrayList output = command(cmdline, ".");
            if (null == output)
                System.out.println("\n\n\t\tCOMMAND FAILED: " + cmdline);
            else
                for (String line : output)
                    System.out.println(line);
    
        }
    }
    

    (The test example is a command that lists all files in a directory and its subdirectories, recursively, in chronological order.)

    By the way, if somebody can tell me why I need four and eight backslashes there, instead of two and four, I can learn something. There is one more level of unescaping happening than what I am counting.

    Edit: Just tried this same code on Linux, and there it turns out that I need half as many backslashes in the test command! (That is: the expected number of two and four.) Now it's no longer just weird, it's a portability problem.

提交回复
热议问题