我的意思是执行一个bash
命令,明确地以字符串的形式传递给bash
,它可以正确处理文件通配符和变量扩展操作。
我尝试了示例命令(请参阅下文了解我实际需要的更“苛刻”的命令):
$ bash -c "files=* ; echo ${files} ; for file in {0..2} ; do echo ${file} ; done"
我得到了 4 个空白行(一行来自echo ${files}
,三行来自)。实际上,这将回显调用环境中的for file in {0..2} ...
变量files
和包含的任何内容,而不是在内部进行评估。file
我实际上需要的是多种事物的组合:
在运行环境和目录中进行适当的评估
files=*
(实际上它会是一种不同的模式,但这并不重要)。${files}
使用for file in ${files}
(而不是for file in {0..2}
)正确循环。使用字符串替换
do mv $file ${file/-0003/-0002}
(而不是do echo ${file}
)。这与从 C++ 调用 的需求相结合system
,迫使我在命令前面加上bash
,就像 一样system("bash -c ...");
。如果我不添加它,则dash
使用默认 shell,它不支持字符串替换,并给出错误sh: 1: Bad substitution
。
这个问题很具体。
此外,任何其他允许我从 C++ 进行系统调用并执行的替代方法:1)文件通配符的使用、2)字符串替换、3)正确的循环,都可以。
答案1
使用数组和适当的引用。例如,给定:
$ ls
file1 file2 file4 file5 file6
然后
$ bash -c 'files=(*) ; echo "${files[@]}" ; for file in "${files[@]}" ; do echo "${file/2/3}" ; done'
file1 file2 file4 file5 file6
file1
file3
file4
file5
file6
答案2
使用双引号时,变量将在调用 shell 中展开。使用单引号:
$ cd /; bash -c 'files=* ; echo ${files} ; for file in {0..2} ; do echo ${file} ; done'
bin boot dev etc home lib lib64 lost+found mnt opt proc root run sbin srv sys tmp usr var
0
1
2
您实际上应该使用数组,但是:
你实际上应该fork
和exec
,如果您想使用特定参数调用特定命令:
#include <unistd.h>
#include <cstdio>
#include <sys/types.h>
#include <sys/wait.h>
int main()
{
pid_t child = fork();
if (child == -1) // fork failed
std::perror("fork");
else if (child == 0) // child
execl("/bin/bash", "bash", "-c", "files=* ; echo ${files} ; for file in {0..2} ; do echo ${file} ; done", NULL);
else // parent
wait(NULL);
}