Reputation: 9488
I'm writing a program in C++ which do some special treatment for all the files in the current directory on Linux OS.
So i was thinking of using system calls such as system("ls")
to get the list of all files.
but how to store it then inside my program ? ( how to redirect the output of ls to let's say a string that i declared in the program )
Thanks
Upvotes: 7
Views: 20214
Reputation: 1
Another way to do it, if you don't want to create too much code is to use > in the shell command to dump it to a file. E.g. ls > ls.out
Upvotes: 0
Reputation: 2390
Using the fork()/exec() and pipe() system calls seems to be the best general method on Unix. This allows easiest separation of the standard output and standard error streams of the invoked program. One can also wait on the spawned process and reap it, collecting its exit status. Finally one can use non-blocking I/O to read from the invoked program's output/error, if need be.
The biggest problem is that to achieve something similar on Windows, you'd possibly need to write several hundred lines of code. I didn't find a better way and haven't studied the problem in the Windows context.
http://support.microsoft.com/kb/190351
Upvotes: 0
Reputation: 366
I would think #2 from pajton is the most fitting answer to the question.
It may be "ls" is not the best example of a command for which you would want to use this since there are other native C library functions available to do this, but there are other programs that generate outputs that you may want to process immediately without having to perform a write/read to file.
#1 is also good on a UNIX/Linux type system that implements an efficient RAM file system that can be used for reading/writing system global data. On almost all systems it's a really good 'quick 'n' dirty' way to get the job done.
Again, most of the responses offer better ways of getting the contents of a directory using native C libraries, but there are instances where functions such as pipe(), fork(), dup(), exec(), system() and popen() are appropriate for communicating with system processes.
Upvotes: 0
Reputation: 777
The consensus seems to be not to use "ls". However, for anyone that is interested in a function to do this:
/**
* Execute a command and get the result.
*
* @param cmd - The system command to run.
* @return The string command line output of the command.
*/
string GetStdoutFromCommand(string cmd) {
string data;
FILE * stream;
const int max_buffer = 256;
char buffer[max_buffer];
cmd.append(" 2>&1"); // Do we want STDERR?
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;
}
Upvotes: 18
Reputation: 53310
I suggest you don't call out to ls
- do the job properly, using opendir/readdir/closedir
to directly read the directory.
Code example, print directory entries:
// $ gcc *.c && ./a.out
#include <stdlib.h> // NULL
#include <stdio.h>
#include <dirent.h>
int main(int argc, char* argv[]) {
const char* path = argc <= 1 ? "." : argv[1];
DIR* d = opendir(path);
if (d == NULL) return EXIT_FAILURE;
for(struct dirent *de = NULL; (de = readdir(d)) != NULL; )
printf("%s/%s\n", path, de->d_name);
closedir(d);
return 0;
}
Upvotes: 7
Reputation: 16226
I see 3 options:
system("ls > tempfile")
and then read the output of ls
from tempfilepipe()
, then use fork()
to spawn a new process. In child process close file descriptor 2 and substitute writing end of pipe for it by calling dup()
. Next, call exec("ls",...)
in child process. Finally read the output of ls
from the pipe in parent processls
for enumerating files in current directory. There are functions to do that right in your program, i.e. opendir(),readdir(),closedir
.I highly recommend option 3.
Upvotes: 0
Reputation: 27542
A simple way to do this is to use the boost filesystem directory iterator. Or just use opendir/readdir/closedir as others have suggested. There is no real upside to the way you are headed.
Code example, print sizes for regular files in a specified directory:
// $ g++ listdir.cc -o listdir -lboost_filesystem && ./listdir
#include <iostream>
#include <boost/filesystem.hpp>
int main(int argc, char* argv[]) {
using std::cout;
using namespace boost::filesystem;
std::string path(argc <= 1 ? "." : argv[1]);
if (is_directory(path)) {
for (directory_iterator itr(path); itr!=directory_iterator(); ++itr) {
cout << itr->path().filename() << ' '; // display filename only
if (is_regular_file(itr->status())) // display size for regular files
cout << " [" << file_size(itr->path()) << ']';
cout << '\n';
}
}
else cout << (exists(path) ? "Found: " : "Not found: ") << path << '\n';
}
Upvotes: 4
Reputation: 49156
I don't think you can use system to read the output.
Try using popen
.
#include <stdio.h>
FILE *popen(const char *command, const char *type);
int pclose(FILE *stream);
But, you probably don't want to do this for ls
. Two reasons:
readdir
), instead of using shell commands and parsing it.ls
output is a bad idea.Upvotes: 10
Reputation: 9764
Either use the approiate c calls to read the files in the directory or you generalize your program so it takes a list of files as input and take that list from ls piped to your program
> ls | yoursoftware
Upvotes: 0
Reputation: 3820
Are you on UNIX or Windows? On UNIX you would create a child process with the fork() call, and then create some pipes and assign the STDOUT of the child process to the STDIN of the parent process. On Windows there is bound to be something similar in the Win32 API.
Upvotes: 2