2

I'm probably missing something, but I'm trying to run commandline from a java

The code is as following:

String command = "sed -i 's/\\^@\\^/\\|/g' /tmp/part-00000-00000";
ProcessBuilder pb = new ProcessBuilder(command);
pb.redirectErrorStream(true);
Process process = pb.start();
process.waitFor();
if (process.exitValue() > 0) {
    String output = // get output form command
    throw new Exception(output);
}

I'm getting the following error:

 java.lang.Exception: Cannot run program "sed  -i 's/\^@\^/\|/g' /tmp/part-00000-00000": error=2, No such file or directory

The fils is exists. I'm doing ll on this file and it is exists. I'm just looking for a way to make it work from java. What am I doing wrong?

Julias
  • 5,752
  • 17
  • 59
  • 84
  • 5
    Not too familiar with Java so just a guess but it looks like it's interpreting the whole string as the name of a command, rather than a series of arguments. – Tom Fenech Feb 19 '15 at 15:25
  • Seems like it would be better, to me, to stream the XML in Java and do the search and replace in Java rather than executing `sed` from an external shell – Kirby Dec 17 '15 at 23:27
  • Very similar question here http://stackoverflow.com/q/20232667/266531 – Kirby Dec 17 '15 at 23:50

4 Answers4

8

Pass the command as an array, not a string:

String[] command={"sed", "-i", "'s/\\^@\\^/\\|/g'", "/tmp/part-00000-00000"};

See ProcessBuilder documentation.

ewan.chalmers
  • 16,145
  • 43
  • 60
5

Honestly there is no need to externally execute sed in this case. Read the file in Java and use Pattern. Then you have code that could run on any platform. Combine this with org.apache.commons.io.FileUtils and you can do it in a few lines of code.

Alternatively, you could use java.util.Scanner to avoid loading the whole file into memory.

    final File = new File("/tmp/part-00000-00000");    
    String contents = FileUtils.readFileToString(file, StandardCharsets.UTF_8.name());
    contents = Pattern.compile("\\^@\\^/\\").matcher(contents).replaceAll("|");
    FileUtils.write(file, contents);

Or, in a short, self-contained, correct example

import org.apache.commons.io.FileUtils;

import java.io.File;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.regex.Pattern;

    public final class SedUtil {
    
        public static void main(String... args) throws Exception {
            final File file = new File("part-00000-00000");
            final String data = "trombone ^@^ shorty";
            FileUtils.write(file, data);
            sed(file, Pattern.compile("\\^@\\^"), "|");
            System.out.println(data);
            System.out.println(FileUtils.readFileToString(file, StandardCharsets.UTF_8));
        }
    
        public static void sed(File file, Pattern regex, String value) throws IOException {
            String contents = FileUtils.readFileToString(file, StandardCharsets.UTF_8.name());
            contents = regex.matcher(contents).replaceAll(value);
            FileUtils.write(file, contents);
        }
    }

which gives output

trombone ^@^ shorty
trombone | shorty
Kirby
  • 15,127
  • 10
  • 89
  • 104
  • I think that using the external sed would be more reliable or at least faster than using java patterns when processing large files. Yes, I known you could read the file line by line, assuming there is enough memory to read these lines. However there are some cases where this pattern approach will not perform well or will throw a OutOfMemoryOhMyGodException because the lines are also huge. Take for instance the angular "transpiled" javascript. And he were very specific in his question - he asked about how to to run sed command from java. – agodinhost Oct 02 '21 at 14:55
  • yeah, that's possible. and other folks might end up here and realize their use case could all be done in platform independent java. Also, it's not a whole lot of change to use a `java.util.Scanner` instead which could process the file line by line. – Kirby Oct 14 '21 at 17:46
0

this code here is magic really, simple and short and tested 100% example i want to remove the last character of line from file (/sdcard/MT2/file.json)

String[] cmdline = { "sh", "-c", "sed -i 's/.$//' /sdcard/MT2/file.json " }; 
try {
  Runtime.getRuntime().exec(cmdline);
} catch (Exception s) {
  finishAffinity();
}

this magic code here don't run only sed, but also runnig echo, cat, ....ect good luck

donquih0te
  • 597
  • 3
  • 22
HishamKanon
  • 25
  • 1
  • 6
-1

Try

Process p = Runtime.getRuntime().exec("sed -i 's/\\^@\\^/\\|/g' /tmp/part-00000-00000");
rgrebski
  • 2,354
  • 20
  • 29