Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

system("command") produces an error; but it works when invoked directly from Bash prompt

Tags:

c++

linux

bash

I am trying to run the following bash command from my C++ program:

diff <(cat /etc/passwd) <(ls -l /etc)

with the following C++ statement:

system("diff <(cat /etc/passwd) <(ls -l /etc)");

The command works fine when running it directly from the Linux shell but when running it from my program, I get:

sh: 1: Syntax error: "(" unexpected

That's referring to the (

I have tried escaping the ( with a \, but that creates more issues:

system("diff <\\(cat /etc/passwd\\) <\\(ls -l /etc\\)");

sh: 1: cannot open (cat: No such file

All I want is to run the following from my C++ program:

diff <(cat /etc/passwd) <(ls -l /etc)

I can create a file and run it, but I leave that as a last option.

like image 899
marko Avatar asked Oct 23 '17 10:10

marko


People also ask

What does $() mean bash?

Example of command substitution using $() in Linux: Again, $() is a command substitution which means that it “reassigns the output of a command or even multiple commands; it literally plugs the command output into another context” (Source).

How do I exit bash mode?

To exit from bash type exit and press ENTER . If your shell prompt is > you may have typed ' or " , to specify a string, as part of a shell command but have not typed another ' or " to close the string. To interrupt the current command press CTRL-C .

What is set +E in bash?

Set –e is used within the Bash to stop execution instantly as a query exits while having a non-zero status. This function is also used when you need to know the error location in the running code.

How do I run a command line argument in bash?

In many cases, bash scripts require argument values to provide input options to the script. You can handle command-line arguments in a bash script in two ways. One is by using argument variables, and another is by using the getopts function.


2 Answers

As mentioned system() creates a new standard shell sh and executes the commands. Since <() is a bash specific feature it can't be interpreted by sh.

You can circumvent this by calling bash explicitly and use the -c option:

system("bash -c \"diff <(cat /etc/passwd) <(ls -l /etc)\"");

or using a raw string literal:

system(R"cmd(bash -c "diff <(cat /etc/passwd) <(ls -l /etc)")cmd");

Here's the relevant part of the system(3) call manual page:

The system() library function uses fork(2) to create a child process that executes the shell command specified in command using execl(3) as follows:

 execl("/bin/sh", "sh", "-c", command, (char *) 0);

system() returns after the command has been completed.

like image 108
user0042 Avatar answered Oct 23 '22 12:10

user0042


The system(3) call invokes /bin/sh to process the command. If you want specifically use bash features, you need to insert bash -c in front of the command string, which will run bash and tell it to process the remainder of the string.

system("bash -c \"diff <(cat /etc/passwd) <(ls -l /etc)\"");
like image 44
gavinb Avatar answered Oct 23 '22 10:10

gavinb