Executando um comando no bash, passado como string, com operação de coringa de arquivo adequada

0

Eu quero executar um comando bash , passado explicitamente como uma string para bash , que pode manipular corretamente as operações de expansão de variáveis e curingas de arquivo.

Eu tentei o comando de amostra (veja abaixo o que eu realmente preciso, que é mais "exigente"):

$ bash -c "files=* ; echo ${files} ; for file in {0..2} ; do echo ${file} ; done"

e eu recebo 4 linhas em branco (uma de echo ${files} e três de for file in {0..2} ... ). Na verdade, isso irá ecoar quaisquer que sejam as variáveis files e file no ambiente de chamada, em vez de avaliar dentro.

O que eu preciso é na verdade uma combinação de coisas para trabalhar:

  1. Avalie corretamente files=* dentro do ambiente e diretório em execução (seria realmente um padrão diferente, mas isso é irrelevante).

  2. Realize o loop corretamente sobre ${files} , com for file in ${files} (em vez de for file in {0..2} ).

  3. Use a substituição de string com do mv $file ${file/-0003/-0002} (em vez de do echo ${file} ). Isso, combinado com a necessidade de chamar de C ++ com system , é o que me força a preceder o comando com bash , como em system("bash -c ..."); . Se eu não o prefixar, o shell padrão dash é usado, o que não suporta a substituição de strings, me dando o erro sh: 1: Bad substitution .

Esta questão é específica.

Além disso, qualquer outra alternativa que me permita fazer uma chamada de sistema a partir do C ++, e executar: 1) uso de curinga de arquivo, 2) substituição de string, 3) loop apropriado, seria ok.

    
por sancho.s 08.05.2017 / 16:26

2 respostas

2

Use uma matriz e a cotação apropriada. Por exemplo, dado:

$ ls
file1  file2  file4  file5  file6

então

$ 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
    
por steeldriver 08.05.2017 / 16:47
1

Com aspas duplas, as variáveis serão expandidas no shell de chamada. Use aspas simples:

$ 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

Você deve usar matrizes, mas:

Você deve realmente fork e exec , se você quiser chamar um comando específico com argumentos específicos:

#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);
}
    
por muru 08.05.2017 / 17:05