有没有人知道从bash命令读入终端输出到c ++的方法?例如,在终端中输入“ls”会返回当前目录中的文件名,有没有办法将这些名称导入到字符串或char数组中?我一直在关注fork()
,exec()
和pipe()
。我试图在子(这里输入的系统命令)和父(这里输出读取)之间打开管道通信,但是完全不成功。想法?
答案 0 :(得分:2)
感谢Kerrek SB,我曾经看到人们以各种方式使用popen(),但不确定这是否是追求与否的途径。在文档的帮助下,将其他人如何使用它的部分组合在一起,我想出了这个。这就是我写的问题具体问题:将命令“ls”中的终端响应导入到文件名向量中。但是,每个文件名都包含一个换行符,我隐式删除了除了字符串文件的最后一个元素之外的所有元素到向量中。
void currentDirFiles( vector<string> & filesAddress )
{
FILE * pipe = popen( "ls", "r" );
char buffer[1000];
string file;
vector<string> files;
while ( fgets( buffer, sizeof( buffer ), pipe ) != NULL )
{
file = buffer;
files.push_back( file.substr( 0, file.size() - 1 ) );
}
pclose( pipe );
filesAddress.swap( files );
}
我正在尝试根据Mankarse的建议调整维基百科RAII示例以满足我的需求,这是我到目前为止所做的。看起来我走在正确的轨道上吗?我对此有任何明显的错误或误解吗?
#include <cstdio>
// exceptions
class file_error { } ;
class open_error : public file_error { } ;
class close_error : public file_error { } ;
class read_error : public file_error { } ;
class TerminalPipe
{
public:
TerminalPipe():
pipeHandle(std::popen("ls", "r"))
{
if( pipeHandle == NULL )
throw open_error() ;
}
~TerminalPipe()
{
std::pclose(pipeHandle) ;
}
void currentDirFiles( vector<string> & filesAddress )
{
char buffer[1000];
string file;
vector<string> files;
while ( fgets( buffer, sizeof( buffer ), pipeHandle ) != NULL )
{
if( std::ferror( pipeHandle ) )
throw read_error();
else
{
file = buffer;
files.push_back( file.substr( 0, file.size() - 1 ) );
}
}
}
private:
std::FILE* pipeHandle ;
// copy and assignment not implemented; prevent their use by
// declaring private.
TerminalPipe( const file & ) ;
TerminalPipe & operator=( const file & ) ;
};
然后用它来调用它:
vector<string> dirFiles;
TerminalPipe pipe;
pipe.currentDirFiles( dirFiles );
答案 1 :(得分:0)
如果使用glibmm c ++绑定,可以执行以下
#include <glibmm.h>
#include <iostream>
#include <unistd.h>
void finished_process(int pid, int ret, Glib::RefPtr<Glib::MainLoop>& loop)
{
loop->quit();
std::cout << "Process finished: " << pid << "|" << ret <<
std::endl;
}
int main()
{
int stdout_fd, stdin_fd, stderr_fd, pid;
Glib::ustring line;
std::vector<std::string> command;
Glib::init();
command.push_back("ls");
command.push_back("-l");
command.push_back("|");
command.push_back("grep");
command.push_back("-i");
command.push_back("my_file");
try{
Glib::spawn_async_with_pipes(".", command,
Glib::SPAWN_SEARCH_PATH | Glib::SPAWN_DO_NOT_REAP_CHILD, sigc::slot<void>(),
&pid, &stdin_fd, &stdout_fd, &stderr_fd);
} catch(Glib::SpawnError &e){
std::cout << "Error: " << e.what() << std::endl;
return 0;
}
Glib::RefPtr<Glib::MainLoop> loop(Glib::MainLoop::create());
Glib::RefPtr<Glib::MainContext> context = loop->get_context();
context->signal_child_watch().connect(sigc::bind(sigc::ptr_fun(finished_process), loop),
pid);
Glib::RefPtr<Glib::IOChannel> io = Glib::IOChannel::create_from_fd(stdout_fd);
loop->run();
while (io->read_line(line) != Glib::IO_STATUS_EOF){
std::cout << line;
}
io->close();
close(stdout_fd);
std::cout << "Exit" << std::endl;
}
编译程序
g++ -g -std=c++0x signal_child_watch_example.cc -o signal_child_watch_example `pkg-config --libs --cflags giomm-2.4`
在Ubuntu / Debian上,可以按如下方式安装glibmm库
sudo apt-get install libglibmm-2.4-dev
注意以后这个2.4版本号可能会改变。相应地更改上面的命令。
来源:http://gtk.10911.n7.nabble.com/Glib-MainContext-signal-child-watch-is-not-working-td43517.html