Using the command line in a c++ program

If you want to use the command line of the system in a C++ program, the basic process is to create a sub-process and let the sub-process complete the execution of the shell command line.

The more direct method is to first create a child process through fork(), and then execute the command line through the exec series of functions in the child process.

The powerful popen function integrates the above functions, and creates a pipeline between the parent and child processes, through which the parent process can perform read and write operations.

introduction

head File

#include <stdio.h>

function prototype

FILE *popen(const char *command, const char *type)

function function

file = popen(cmd,"r");

popen() will call fork() to generate a child process, and then call /bin/sh -c from the child process to execute the instruction of the parameter command. The parameter type can use "r" to represent read, and "w" to represent write. If the type is "r", the file pointer is connected to the standard output of the command, and the standard output of the command is read; if the type is "w", the file pointer is connected to the standard input of the command, and the standard input of the command is written.

According to this type value, popen () will establish a pipeline connected to the standard output device or standard input device of the child process, and then return a file pointer. The process can then use this file pointer to read from or write to the standard output device of the child process.

routine

#include <iostream>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>

void myCommand(char* cmd){
    FILE* file;
    file = popen(cmd,"r");
    while (fgets(cmd, (int)strlen(cmd), file) !=nullptr) {
    }
    pclose(file);
}

int main(int argc, const char * argv[]) {
    char cmd[2048];
    char zipName[512];
    char path[1024];
    //测试使用的是zip指令,只要把完整指令放在cmd字符数组里就行
    strcpy(zipName,"/Users/zhangzhehao/fileTest");
    strcpy(path,"/Users/zhangzhehao/fileTest");
    //将需要使用的命令行拼出来
    snprintf(cmd, 2048, "zip -r -j %s.zip %s", zipName, path);
    //将命令行作为参数
    myCommand(cmd);
    std::cout << "Hello, World!\n";
    return 0;
}

The test in the above routine is to use zip to compress the file command. In fact, the test function can be simpler:

#include <iostream>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>

void myCommand(char* cmd){
    FILE* file;
    file = popen(cmd,"r");
    while (fgets(cmd, (int)strlen(cmd), file) !=nullptr) {
    }
    pclose(file);
}

int main(int argc, const char * argv[]) {
    char cmd[2048];
    strcpy(cmd,"ls");
    //将命令行作为参数
    myCommand(cmd);
    std::cout << "Hello, World!\n";
    return 0;
}

In this way, the ls command can be tested and all files in the current directory can be displayed.

It should be noted that popen returns a file pointer, through which we read the standard output device of the child process or write to the standard input device of the child process, that is, actually pass cmd to the child process, so that the child process can execute cmd.

The mycommand function can also be written more robustly:

std::string myCommand(char* cmd) {
    std::array<char, 128> buffer;
    //记录运行结果的字符串
    std::string result;
    //popen:创建一个管道,调用fork产生一个子进程,执行一个shell以运行命令开启一个进程
    //pclose:关闭标准IO流
    std::unique_ptr<FILE, decltype(&pclose)> pipe(popen(cmd, "r"), pclose);
    if (!pipe) {
        result = "error";
        return result;
    }
    while (fgets(buffer.data(), buffer.size(), pipe.get()) != nullptr) {
        //记录指令行
        result += buffer.data();
    }
    return result;
}

Spoiler: the use of zip

 zip -r /Users/fileTest.zip /Users/fileTest

The above command will compress the files in the fileTest folder and store them in the Users folder in the form of fileTest.zip. 

But there will be a problem here, the fileTest.zip will also add the Users folder to the compressed content, that is to say

The contents of fileTest.zip are:

Users文件夹->fileTest文件夹->被压缩的各种文件

Most of the time we just want these to be compressed:

fileTest文件夹->被压缩的各种文件

Therefore, the command "-j" needs to be added to the command line.

zip -r -j /Users/fileTest.zip /Users/fileTest

Only the last folder will be saved in this compressed file.

Guess you like

Origin blog.csdn.net/m0_37872216/article/details/126961271