0

I am running sed command in java program when i execute my java file in linux. when i ran the command alone in linux, this will work -> sed '1d;$d' /home/sample/testdata.txt > /home/output/testupdate.txt

however when i ran my java program in linux, its returning exit(1) error . i have read through and use as an array but its still failing .

public static void main(String[] args) {
    String[] cmd = {"sed", "sed '1d;$d' /home/sample/testdata.txt > /home/output/testupdate.txt"};
    String s;
    Process p;
    try {
        p = Runtime.getRuntime().exec(cmd);
        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) {
    }
}
Farid Arshad
  • 334
  • 2
  • 14
  • 1
    I have my doubts you can pass `>` as an argument and having it parsed as "output redirection". See [here](https://stackoverflow.com/questions/4741878/redirect-runtime-getruntime-exec-output-with-system-setout) for a better way. – Federico klez Culloca Jun 22 '21 at 12:16
  • 1
    '>' is shell syntax, and I don't think you're running a shell via 'exec'. – iggy Jun 22 '21 at 12:18
  • 4
    You don’t need `sed` at all. Java can do everything `sed` can do. And using Java means it can run on systems that don’t have `sed` installed (like Windows). – VGR Jun 22 '21 at 12:22
  • 2
    Does this answer your question? [Runtime's exec() method is not redirecting the output](https://stackoverflow.com/questions/16238714/runtimes-exec-method-is-not-redirecting-the-output) – Joe Jun 22 '21 at 12:40
  • @Joe , this is able to launch execute from .sh file. but i am trying to execute within java itself without the need to create an additional .sh script – Farid Arshad Jun 22 '21 at 12:44

2 Answers2

2

Java is not a shell so does not handle redirects - your original command only works via your Linux shell which understands ">".

You can make Java launch the shell to execute the command, say if you are using bash:

 String[] cmd = {"/bin/bash", "-c"
    , "sed '1d;$d' /home/sample/testdata.txt > /home/output/testupdate.txt"};

Alternatively see the other helpful comments which link to other pages on dealing with the redirects within the Java code, or to do it inside Java itself (such as with Files.lines / streams).

DuncG
  • 12,137
  • 2
  • 21
  • 33
  • this work fine but i was wondering what does "-c" mean, tried googling but i could not find what is it for – Farid Arshad Jun 23 '21 at 04:11
  • The "-c" tells bash to run the given command, then exit. Without "-c" bash will assume the parameter is a script. Compare `bash ls` vs `bash -c ls`. – DuncG Jun 23 '21 at 08:46
2

You don’t need sed. Java can do everything sed can do.

In your case, it appears you are using sed to remove the first and last line from a file. Here’s how you would do that in Java:

Path source = Path.of("/home/sample/testdata.txt");
Path destination = Path.of("/home/output/testupdate.txt");

long lineCount;
try (Stream<?> lines = Files.lines(source)) {
    lineCount = lines.count();
}

long lastLine = lineCount - 1;

try (BufferedReader in = Files.newBufferedReader(source);
     BufferedReader out = Files.newBufferedWriter(destination)) {

    // Skip first line
    String line = in.readLine();

    long counter = 0;
    while ((line = in.readLine()) != null) {
        if (++counter < lastLine) {
            out.write(line);
            out.newLine();
        }
    }
}

If for some reason you absolutely need to use an external process, there are many other questions and answers which cover your mistake: > is not understood by sed. Normally, it is the shell (like bash) which interprets file redirection.

The proper way to run your command would have been:

ProcessBuilder builder =
    new ProcessBuilder("sed", "1d;$d", "/home/sample/testdata.txt");

builder.redirectOutput(new File("/home/output/testupdate.txt"));
builder.redirectError(ProcessBuilder.Redirect.INHERIT);

Process p = builder.start();
VGR
  • 40,506
  • 4
  • 48
  • 63