1

I was learning about Unix file system and learned about pipes. According to GeeksForGeeks,

A pipe holds the output of the first command till it has been read by the second program

So, I was thinking if I could link a C program and a Java Program so as to supply the output of the C code as the command line arguments for the Java code.

Here are my codes:

c.c

#include <stdio.h>
int main(){
    printf("World");
    return 0;
}

Java.java

public class Java{
    public static void main(String[] a){
        System.out.println("Hello "+a[0]); 
    }
}

I tried to link the C object file execution command and the Java class execution command so that the output turns out to be:

Hello World

This is what I tried:

gcc -o c c.c
javac Java.java

./c | java Java

It didn't go as I expected. The Java program didn't receive the output of the C program and simply threw an ArrayIndexOutOfBounds exception. Also, I didn't see the output of the C program.

How can I achieve my goal, if at all this is possible?

7
  • 1
    You’ve swapped “arguments” for “input”....
    – Jeff Schaller
    Apr 8, 2018 at 16:14
  • 2
    @reviewers: This question is about pipes and command line arguments handling, not about programming... Apr 8, 2018 at 16:41
  • Been a long time since I've done C/C++ programming, but aren't you trying to access an argument to your ./c program that you didn't provide (in your example at least)? First make sure each program works as expected individually - THEN tie them together with a pipe (or xargs or i/o redirection or ....)
    – ivanivan
    Apr 8, 2018 at 16:54
  • @ivanivan The C and Java programs work perfectly individually. The ./c command executes the C object file and shows World as the output.
    – progyammer
    Apr 8, 2018 at 18:02
  • 1
    You need to use stdin in Java not arguments. if you don't know how to do it I think your question belong to stack overflow here's probably your answer stackoverflow.com/q/13095983/1195001
    – Kiwy
    Apr 8, 2018 at 19:49

2 Answers 2

2

What you want is possible but not as easily as you tried. As you correctly stated a pipeline provides input, not command line arguments.

Luckily there is a (standard) program which does just that: xargs

In the GNU world (Linux) the best way would be to separate the output elements with literal zero bytes:

/your/c/program | xargs --no-run-if-empty -0 /your/java/program

You can easily try this with echo (which is the default command for xargs anyway`:

echo '/bin
/etc
/usr' | xargs ls -ld
2
  • Wow! It worked like a charm. So basically, xargs feasibly converts the output of command 1 as arguments to be provided to command 2. Is that correct?
    – progyammer
    Apr 8, 2018 at 18:05
  • 1
    @progyammer Yes, in general. This can be configured in several ways. You should have a look at man xargs to get an impression of the important options. Apr 8, 2018 at 18:09
1

What you want is possible and easy.  Just type

/your/java/program "$(/your/c/program)"

The $(…) notation is called “command substitution”.  $(command1) runs command1 with output to a pipe, captures it, and puts it on the command line.  So

command2 $(command1)
runs command2 with command1’s output as a command-line argument.  You should add quotes ("…") to handle the case where the output from command1 (i.e., your C program) is multiple words (e.g., printf("planet earth");).  This is what you are asking for.

I discuss this in some length here, where I show the example

$ ls -ld "$(date "+%B %Y").txt"
-rwxr-xr-x  1 username groupname    687 Apr  2 11:09 April 2018.txt

P.S. If you are on a very old or unusual system, the $(…) notation might not work.  In that case, try

/your/java/program "`/your/c/program`"

`…` is an old version of $(…).  If $(…) works on your system, use it.

0

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .