将bash命令的终端响应读取到c++变量中
Reading terminal response to bash commands into c++ variable
有谁知道从bash命令读取终端输出到c++的方法吗?例如,在终端中输入"ls"将返回当前目录中的文件名,是否有办法将这些文件名导入到字符串或字符数组或其他东西中?我一直在研究fork()
, exec()
和pipe()
。我试图打开子(这里输入的系统命令)和父(这里读取的输出)之间的管道通信,但完全不成功。想法吗?
感谢Kerrek SB,我看到人们以各种方式使用popen(),但不确定这是否是要追求的路线。在文档的帮助下,并将其他人如何使用它的部分内容放在一起,我想出了这个。这就完成了我在文章中提出的问题:将命令"ls"中的终端响应导入到文件名向量中。但是,每个文件名都包含一个换行符,我隐式地删除了该换行符,将字符串文件中除最后一个元素外的所有元素都推回到vector中。
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 );
如果使用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
- 如何创建一个CMake变量,除非显式重写,否则使用默认值
- 将成员变量添加到共享库中的类中,不会破坏二进制兼容性吗
- 将数组的地址分配给变量并删除
- 为"adjacent"变量赋值时出现问题
- enum是C++中的宏变量还是整数变量
- 在全局变量中保存类的实例以重新创建类(创建"backup")
- 用C++中的一个变量定义一个常量
- 具有奇怪重复模板模式的派生类中的成员变量已损坏
- 你能重载对象变量名本身返回的内容吗
- 内置函数可查看CPP中的成员变量
- 是否可以初始化不可复制类型的成员变量(或基类)
- 尝试通过多个向量访问变量时,向量下标超出范围
- 试图让变量检查数组中的某些内容
- Cpp-Tuple使用带有变量的get
- 将包含C样式数组的对象初始化为成员变量(C++)
- 当vector是tje全局变量时,c++中vector的内存管理
- 通过多个头文件使用常量变量
- std::threads可以从Windows DLL中的全局变量创建/销毁吗?
- 执行函数时导致崩溃的变量
- 变量没有改变?通过向量的函数调用