如何在system()中使用通配符表达式

时间:2014-11-18 17:13:47

标签: c++ linux shell system wildcard

以下命令在我的嵌入式Linux(Beaglebone Black)上正常运行:

echo bone_pwm_P9_21 > /sys/devices/bone_capemgr.?/slots

但不是在使用这个小型C ++程序时:

#include <stdlib.h>
#include <string>

int main {
    system(std::string("echo bone_pwm_P9_21 > /sys/devices/bone_capemgr.?/slots").c_str());
    return 0;
}

问题涉及'?'问号,用作通配符。 当传递给std::string的{​​{1}}中的问号被替换为普通字符时,system()函数会对命令进行完美评估。

我尝试过的解决方案没有成功:

  • system()替换为?
  • \?替换为?

2 个答案:

答案 0 :(得分:2)

除了您的代码无法编译之外,此操作失败,因为system(3)运行sh,通常是dashbusybox提供的最小外壳。

同时,您的互动式登录使用bashksh或其他一些更舒适的shell。

dashbusybox sh不会对重定向执行全局展开,而bashksh会执行。以下是您希望bash提供的行为的演示:

$ touch file.txt

$ bash -c 'echo "bash contents" > *.txt'

$ cat file.txt
bash contents

与此同时,您遇到的问题包括: dash

$ dash -c 'echo "and now dash" > *.txt'

$ ls
*.txt  file.txt

$ cat '*.txt'      # Instead of expanding, the path was taken literally
and now dash

$ cat file.txt
bash contents

要解决此问题,您可以(按优先顺序)

  1. 用C代码而不是shell脚本编写C程序
  2. 使用execve调用更好的shell。
  3. 重写不写入glob,例如echo "stuff" | tee *.txt > /dev/null
  4. 使用system调用更好的shell,例如bash -c "echo stuff > *.txt"

答案 1 :(得分:1)

注意:正如πάνταῥεῖ指出system()命令调用shell,当使用正确的通配符时,它通常会进行扩展:*。如果您希望控件单独进行每个system()调用或者底层shell受限,那么这个答案更合适。

原始回答:

也许您可以使用 wordexp 来构建字符串,然后再进行system()调用:

#include <string>
#include <vector>
#include <iostream>
#include <wordexp.h>

std::vector<std::string> expand_env(const std::string& var, int flags = 0)
{
    std::vector<std::string> vars;

    wordexp_t p;
    if(!wordexp(var.c_str(), &p, flags))
    {
        if(p.we_wordc)
            for(char** exp = p.we_wordv; *exp; ++exp)
                vars.push_back(exp[0]);
        wordfree(&p);
    }
    return vars;
}

int main()
{
    for(auto&& s: expand_env("$HOME/*")) // <= Note the wildcard '*'
        std::cout << s << '\n';
}

在您的具体情况下,您可以使用以下内容:

int main()
{
    std::vector<std::string> devices = expand_env("/sys/devices/bone_capemgr.*/slots");

    for(std::vector<std::string>::size_type i = 0; i < devices.size(); ++i)
        system(("echo bone_pwm_P9_21 > " + devices[i]).c_str());
}