在 bash 中执行命令,以字符串形式传递,并使用适当的文件通配符操作

在 bash 中执行命令,以字符串形式传递,并使用适当的文件通配符操作

我的意思是执行一个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

我实际上需要的是多种事物的组合:

  1. 在运行环境和目录中进行适当的评估files=*(实际上它会是一种不同的模式,但这并不重要)。

  2. ${files}使用for file in ${files}(而不是for file in {0..2})正确循环。

  3. 使用字符串替换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

您实际上应该使用数组,但是:

你实际上应该forkexec,如果您想使用特定参数调用特定命令:

#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);
}

相关内容