Search code examples
javashellunixruntimepipeline

Why executing system command with pipeline in Java fail without whitespaces?


In the shell command line both commands are legit and run without a problem:

# without whitespaces
parted /dev/sdd print free -m|grep free

and

# with whitespaces
parted /dev/sdd print free -m | grep free

However, as soon as I run from Java the former version of it (the one without white spaces), i.e.:

Runtime.getRuntime().exec("parted /dev/sdd print free -m|grep free")

It fails:

2019-09-10 18:33:34.012  WARN 2528 --- [           main] Utils      : Error running parted /dev/sdd print free -m|grep free: parted: invalid option -- '|'
parted: invalid option -- 'g'
parted: invalid option -- 'r'
parted: invalid option -- 'e'
parted: invalid option -- 'p'
Usage: parted [-hlmsv] [-a<align>] [DEVICE [COMMAND [PARAMETERS]]...]

However, the same java line with the latter command version (the one with whitespaces) runs perfectly fine.
Obviously '|'-symbol doesn't get recognized when run from Java. The question is why?


Solution

  • The rules used by the Java exec function are not the rules used by the shell.

    exec splits into tokens based on whitespace.

    thus foo|bar is a single token. Shell parsing, by contrast, will treat it as 3 separate elements, foo, |, and bar. The man pages for bash spell out bash processing for you in great detail.