Crie 2 arquivos de nome similar com conteúdo da saída de 2 linhas de um comando

3

Eu executo cmd e saem 2 linhas de texto:

$ cmd
foo
bar

Eu preciso escrever isso para: '/long/path/x.{load,conf}

Escrever para este destino requer privilégios de superusuário, o que exclui manualmente:

$ echo "foo" > /long/path/x.load
$ echo "bar" > /long/path/x.conf

como "o redirecionamento é feito antes que o comando (sudo) seja iniciado e adquira privilégio"

Considerando que foo e bar são eles próprios substitutos de cadeias de texto de difícil controle, qual é a melhor maneira de conseguir isso?

Na verdade, estou procurando uma solução que cause menos arranhões na cabeça, pois isso representa um passo em uma sequência de instruções, e seria bom escrever código que fala por si, mas estou sempre interessado em todas as possíveis maneiras de fazer alguma coisa.

    
por P-i- 06.06.2015 / 22:31

3 respostas

2

Operador de redirecionamento do Awk é útil aqui. Aqui estão algumas variações sobre este tema.

cmd | sudo awk '{print >"/long/path/x." (NR==1 ? "load" : "conf")}'
cmd | sudo x=/long/path/x awk 'NR==1 {print >ENVIRON["x"]".load"}
                               NR==2 {print >ENVIRON["x"]".conf"}'
cmd | sudo awk 'FNR==1 && NR!=1 {exit} {print >ARGV[NR-1]}' -  /long/path/x.{load,conf}

O primeiro é o mais curto e o mais simples possível. Cada linha é impressa no nome do arquivo determinado pela avaliação da expressão após o operador > . O número da linha atual NR é usado para calcular o nome do arquivo. A justaposição de expressões é o operador de concatenação de strings no awk.

    
por 07.06.2015 / 01:06
1

As pessoas geralmente fazem isso com tee :

cmd | sudo tee /long/path/x.{load,conf}

tee grava cópias de sua entrada em todos os seus arquivos de saída nomeados - e, da mesma forma, o redirecionamento ocorre antes de um exec , portanto, também gera o argumento na expansão de chaves. Portanto, o acima deve funcionar bem e gravar os dois nomes de arquivos resultantes de uma só vez e o padrão.

Se você preferir não ver o que o tee escreve em seu terminal, já que ele copia os dados, você pode redirecionar o padrão para /dev/null - sudo não irá interferir nesse redirecionamento.

Você deve notar que - como escrito - tee irá truncar os arquivos de saída antes de escrever para eles. Se você quisesse anexar, você poderia simplesmente adicionar a opção -a ppend e tee iria copiar os dados de entrada para a cauda de todos os arquivos de saída nomeados.

Para escrever cada linha para locais separados é um pouco mais difícil admitidamente. Mas sed oferece o comando w rite. Combine-o com seu argumento -e xpression e você poderá escrever todo o script sed com a expansão de chaves:

cmd | sudo sed -e'$x;/./w '/long/path/x.{load,conf}$'\n1x'

... irá w ritar a primeira linha para o primeiro arquivo de argumento e a segunda linha para o segundo. As alterações e x apenas equilibram o script nas primeiras e segundas linhas - para impedir que sed escreva ambas as linhas nos dois arquivos para cada linha.

Eu testei como:

printf %s\n 1 2 | 
sed -e'$x;/./w '/tmp/{1,2}$'\n$!x'

... e depois correu ...

head /tmp/[12]

... que imprimiu ...

==> /tmp/1 <==
1
==> /tmp/2 <==
2
    
por 07.06.2015 / 08:07
0

Não tenho certeza se você quer uma solução para fazer o script da coisa toda (do comando cmd para as configurações .load e .conf files, mas conforme a configuração desses arquivos você ainda pode fazer isso usando o sudo mas você realmente precisa do redirecionamento para fazer parte do comando sudoed :

$ sudo sh -c "echo 'foo' > /long/path/x.load"
$ sudo sh -c "echo 'bar' > /long/path/x.conf"

Aqui, sudo terá privilégio maior e, em seguida, executará sh shell, que, por sua vez, interpretará o comando fornecido e, somente nesse momento, o redirecionamento ocorrerá, evitando qualquer problema de privilégio.

Se por acaso você precisar fazer o script, dependendo das suas necessidades, isso pode parecer algo assim:

cmd | {
    read line
    sudo sh -c "echo '$line' > /long/path/x.load"
    read line
    sudo sh -c "echo '$line' > /long/path/x.conf"
}
    
por 06.06.2015 / 22:49