-1

  String str;
            Process p;
            try {
                String command = "wmctrl -l|awk '{$1=\"\"; $2=\"\"; $3=\"\"; print}'";
                p = Runtime.getRuntime().exec(command);
                BufferedReader br = new BufferedReader(
                        new InputStreamReader(p.getInputStream()));
                while ((str = br.readLine()) != null) {

                        activeWindowtitles.add(str);
                        System.out.println(str);
                }
                p.waitFor();
                p.destroy();
            } catch (Exception ex) {
            }

I am writing a java code to get all applications name in Linux system. I found a command to achieve this. I ran this command in Terminal and it works fine. But it is not working in Java code as i want only applications name instead of other details. The command is "wmctrl -l | awk '{$1=""; $2=""; $3=""; print}'" I am getting full output after executing this in java code.

Please tell me how to write this command properly.. Thanks

Ankush
  • 9
  • 2
  • If your are using a command with arguments, you have to split the command into an array! Btw: I suggest using ```ProcessBuilder``` instead of ```Runtime```, it's easier to handle! For further details, have a look at: https://thilosdevblog.wordpress.com/2022/09/18/how-to-properly-handle-the-output-of-the-processbuilder/ – Thilo Schwarz Feb 04 '23 at 10:34
  • 1
    This issue keeps on appearing, as mentioned above you have to run a shell to interpret shell operations like `|`. See [Exit(1) when running exec on java](https://stackoverflow.com/questions/68083327/exit1-when-running-exec-on-java) or build the pipeline stream in Java with `ProcessBuilder.startPipeline()` – DuncG Feb 04 '23 at 11:32
  • The best solution to this by far is to stop using awk altogether. Java can do everything awk can, and much more. You only need `new ProcessBuilder("wmctrl", "-l").start();`. – VGR Feb 04 '23 at 16:14

1 Answers1

0

Personally I would put the wmctrl command in a script and do something like this:

public static List<String> getRunningApps(String executablePath) throws IOException, InterruptedException {
    final String ERR_LOG_PATH = "stderr.log";
    List<String> result = new ArrayList<>();
    ProcessBuilder pb = new ProcessBuilder(executablePath);
    pb.redirectError(new File(ERR_LOG_PATH));
    Process p = pb.start();
    int exitCode = p.waitFor();
    if (exitCode != 0) {
        throw new RuntimeException(String.format("Error get apps. Check error log %s%n", ERR_LOG_PATH));
    }
    try (Scanner s = new Scanner(p.getInputStream())) {
        while (s.hasNextLine()) {
            result.add(s.nextLine().trim());
        }
    }
    return result;
}

That way you can tweak it more easily and keep your code cleaner. The script I used was:

#!/bin/bash
wmctrl -l | awk '{$1=""; $2=""; $3=""; print}'
g00se
  • 3,207
  • 2
  • 5
  • 9