Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
2.4k views
in Technique[技术] by (71.8m points)

string - C++ system() command path with spaces

How do I use the system() function in c++ if I want to enter a command that needs a path when my path has spaces in it? Example code:

#include <iostream>

int main()
{
    std::string command = "ls -la /home/testuser/this is a folder/test/";
    std::cout << "Click enter to execute command..." << std::endl;
    getchar();
    std::system(command.c_str());
    return 0;
}

This doesn't work supposedly because the shell needs backspaces in front of a space. Unfortunately this doesn't work too:

std::string command = "ls -la /home/testuser/this is a folder/test/";

Any idea what I'm doing wrong or how I could do it better? Thanks.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Ask yourself: how would you execute this command, yourself, from a shell prompt?

$ ls -la /home/testuser/this is a folder/test/

This, of course, will not work for the same reason your program fails. Instead, as every primer on shell scripting teaches you, you need to quote the parameter:

$ ls -la "/home/testuser/this is a folder/test/"

That will work, and you use system() in exactly the same way:

std::string command = "ls -la "/home/testuser/this is a folder/test/"";

But what's even better is not using system() in the first place. All the system() is, for all practical purposes, is a fork(), followed by exec() in the child process, with the parent process wait()ing for the child process's termination.

The problem is that the child process exec() the system shell, which parses the command according to its rules. This includes all the normal things that occur when executing the command via the shell directly: filename expansion, globbing, and other things.

If the string that gets passed to exec() includes any special shell characters, they'll be interpreted by the shell. In this case, you're intentionally using this to correctly parse the command string, in order to pass the correct arguments to /bin/ls.

When executing a specific, fixed command, this is fine. But when the actual command varies, or contains externally-specified parameters, it is your responsibility to correctly handle any shell wildcard characters in order to get your intended result. Hillarity ensues, otherwise. In that situation, you will find that using fork() and exec() yourself will produce far more deterministic, and reliable results, where you are in complete control of all arguments that get passed to the command being executed, instead of relying on the system shell to do it for you.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...