2

I am new to both Java and Linux, I was trying to use some Runtime.exec() commands that would allow my program to execute commands in Linux such as "cd /mnt/" and "ls --group-directories-first" to list files and directories contained in /mnt/ but I think I am making a problem with the execution.

I tried my code to only include the "ls --group-directories-first" and it worked like a charm, only problem was, it only listed subdirectories and files in the projects folder. I wanted to make my program go to /mnt/ first so I made my command line to a command array by using exec(String[] cmdarray) format as process1 = Runtime.getRuntime().exec(new String[]{"cd /mnt/","ls --group-directories-first"}); and when I ran it on linux, it just got executed without any printed runtime errors but also without any feedback/printed lines.

Here is my code:

import java.io.BufferedReader;
import java.io.InputStreamReader;

public class linCom {
    public static void main(String args[]) {
        String s;
        Process p;

        try {
            p = Runtime.getRuntime().exec("ls --group-directories-first");
            BufferedReader br = new BufferedReader(
                    new InputStreamReader(p.getInputStream()));
            while ((s = br.readLine()) != null)
                System.out.println("line: " + s);
            p.waitFor();
            System.out.println ("exit: " + p.exitValue());
            p.destroy();
        } catch (Exception e) {}


    }
}

This worked and printed out:

"line: DummyFolder1

line: linCom.class

line: linCom.java

exit: 0"

import java.io.BufferedReader;
import java.io.InputStreamReader;

public class linCom {
    public static void main(String args[]) {
        String s;
        Process p;

        try {
            p = Runtime.getRuntime().exec(new String[]{"cd /mnt/","ls --group-directories-first"});
            BufferedReader br = new BufferedReader(
                    new InputStreamReader(p.getInputStream()));
            while ((s = br.readLine()) != null)
                System.out.println("line: " + s);
            p.waitFor();
            System.out.println ("exit: " + p.exitValue());
            p.destroy();
        } catch (Exception e) {}


    }
}

This just got executed with no printed lines.

I expected my program to just go to the /mnt/ directory and print out subdirectories and files on there, but it just got executed with no visible runtime errors and no printed lines.

I have looked at other entries but could not find any answer to my problem.

EDIT: I changed "no errors" with "no error messages" to make it clear that if program had any errors, I did not get any feedback about it.

O. Jones
  • 103,626
  • 17
  • 118
  • 172
Anthony
  • 69
  • 9
  • 2
    Just for the record: **never** go with empty catch blocks. There is no point in ignoring errors. At least go "e.printStackTrace()" for example. – GhostCat Sep 16 '19 at 11:50
  • "This just got executed with no errors " ... how would you now if you suppress exceptions? But well, the point here is: you cant "combine" commands like that. – GhostCat Sep 16 '19 at 11:51
  • Open a terminal and type out those commands yourself. What is the output you get? Are you sure there are subdirectories in `/mnt`? – Some programmer dude Sep 16 '19 at 11:53

3 Answers3

3

Here's where the UNIX process model can be confusing.

What you have tries to run the program named cd /mnt/ with the first parameter of ls --group-directories-first . Unix programs can be named anything (they're just filenames) but there's no program named cd /mnt. And anyway, the cd operation is actually performed by a shell, not as a forked/execed program.

You hope to run this shell command from your Java program: cd /mnt/; ls --group-directories-first . The trouble is, Java's .exec() method does not give you a shell, so shell commands don't work.

You can try this instead. It's like running the shell command

/bin/sh -c "cd /mnt/; ls --group-directories-first"

With this, you start a shell, then tell it to run -cthe command you want.

Process p = Runtime.getRuntime().exec(new String[]{"/bin/sh",
                                                   "-c",
                                                   "cd /mnt/; ls --group-directories-first"});  

But it's quite dependent on the machine where your Java program runs, so be careful.

Reference: How to invoke a Linux shell command from Java

O. Jones
  • 103,626
  • 17
  • 118
  • 172
  • Thank you, that was exactly my problem and you solved it! Too bad I cannot vote as I have <15 points. – Anthony Sep 16 '19 at 12:09
2

Do not use an external process just to list files. Java has plenty of ways to do that. All of them are in the Files class. For example:

Path dir = Paths.get("/mnt");
try (Stream<Path> files = Files.list(dir).sorted(
    Comparator.comparing((Path p) -> !Files.isDirectory(p))
        .thenComparing(Comparator.naturalOrder()))) {

    files.forEach(System.out::println);
}
VGR
  • 40,506
  • 4
  • 48
  • 63
1

Do you really need to use Runtime.exec()comands? That would make your code platafform dependent.

You could use File.listFiles():

File folder = new File("/mnt");
for (File f : folder.listFiles()) {
    System.out.println(f.getName());
}

That would make the code less plataform dependent