How to Capture the Output of a Linux Command in C++
Last Update: Jul 11, 2021
Ok, I admit this is a pretty obscure one, but this came up for a task at work today, and I had forgotten how to do this. I Googled around a bit and found many answers I either didn’t understand entirely or just seemed too complicated for what I was trying to accomplish. I had done this with the boost libraries before, but I didn’t have them on this machine, so I wanted a clean, stdlib type solution.
Want to learn more about C++? Check out this C++ fundamentals course. It covers C++ 17!
I dug around and found this snippet of code on my hard drive and put something together to make it work. I didn’t write it, and I don’t remember where it came from, so I can’t give credit for it, but it works like a charm:
(tested using G++ v. 4.4.4)
string GetStdoutFromCommand(string cmd) {
string data;
FILE * stream;
const int max_buffer = 256;
char buffer[max_buffer];
cmd.append(" 2>&1");
stream = popen(cmd.c_str(), "r");
if (stream) {
while (!feof(stream))
if (fgets(buffer, max_buffer, stream) != NULL) data.append(buffer);
pclose(stream);
}
return data;
}
As you can see, this is a function, and you pass the command as a string to that function. It’s straightforward to use. As a note, you can run system commands from within C using system.
The problem with this is, the command is often run first, before any output commands and the function returns an integer indicating success or failure, but not the output of the string. The function above fixes that for you.
What it does is creates a buffer, opens up a read-only stream, runs the command, and captures the output, stuffs it into the buffer, then returns it as a string.
Here is how we put it to use:
int main() {
string ls = GetStdoutFromCommand("ls -la");
cout << "LS: " << ls << endl;
return 0;
}
Keep in mind that there is no real checking here, and you should test the outputs of the commands carefully. For instance, when I used it today, I had long commands where I piped the output into into grep and cut, etc. If I got unexpected output, it caused a problem that hung the executable. So you want to make sure and validate your input and output as you go along, don’t just go running a bunch of commands and working on the output without some good error checking.
Here is the full code:
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
using namespace std;
string GetStdoutFromCommand(string cmd) {
string data;
FILE * stream;
const int max_buffer = 256;
char buffer[max_buffer];
cmd.append(" 2>&1");
stream = popen(cmd.c_str(), "r");
if (stream) {
while (!feof(stream))
if (fgets(buffer, max_buffer, stream) != NULL) data.append(buffer);
pclose(stream);
}
return data;
}
int main() {
string ls = GetStdoutFromCommand("ls -la");
cout << "LS: " << ls << endl;
return 0;
}
As I said, this is pretty obscure, but I figured if I had this problem, others might as well. I thought I’d throw it out there. I hope it helps.
Happy Coding!
If you’d like to learn more, here’s a great C++ fundamentals course.
Advanced C++ developers wanting to level up should check out High-performance computing in C++
Follow @JeremyCMorgan