Eu tenho file.txt com comando armazenado em uma linha (este comando é válido quando executado no console) e quero executá-lo em uma linha com sh like
cat file.txt | eval
O que está faltando? alguma dica?
e se eu tiver um arquivo com muitos comandos (um para cada linha) e quiser executar apenas um comando (uma linha inteira)? minha primeira ideia é:
head -n5 | tail -n1 | eval
Responder1
eval
não lê sua string de comando do stdin.
eval "$(cat file.txt)"
# or easier, in ksh/bash/zsh
eval "$(<file.txt)"
# usually you cannot be sure that a command ends at the end of line 5
eval "$(head -n 5 file.txt)"
Em vez disso, eval
você pode usar padrão .
ou bash
/ zsh
/ ksh
source
se os comandos estiverem em um arquivo de qualquer maneira:
source ./file
(observe que é importante adicionar isso ./
. Caso contrário, source
procure file
in $PATH
antes de considerar o file
no diretório atual. Se estiver no modo POSIX, bash
nem consideraria o file
no diretório atual, mesmo que não seja encontrado em $PATH
).
Isso não funciona na escolha de uma parte do arquivo, é claro. Isso poderia ser feito por:
head -n 5 file.txt >commands.tmp
source ./commands.tmp
Ou (com ksh93, zsh, bash):
source <(head -n 5 file.txt)
Responder2
então... uma solução para sua pergunta é 100% possível e (no contexto de make
) importante.
Encontrei isso com um makefile e, dada a dificuldade de aninhar comandos bash em um makefile que já usa $(...)
para chamar variáveis, é bom poder fazer exatamente o que você está perguntando.
Em vez de usar eval
, basta usar o comando do sistema awk
ou :perl
// command_list.sh:
echo "1"
echo "2"
echo "3"
// command line prompt:
$: cat command_list.sh | awk '{system($0)}'
1
2
3
E, construção de comando:
// a readable version--rather than building up an awk miniprogram,
// split into logical blocks:
$: cat inputs.txt | awk '{print "building "$1" command "$2" here "}' | awk '{system($0)}'
Responder3
Tecnicamente, é impossível avaliar algo em seu ambiente atual se você quiser lê-lo em um canal, pois cada comando no pipeline é executado como um processo separado.
No entanto, dependendo do que você está tentando realizar, isso pode não importar. De qualquer forma, aqui está eval
o conteúdo de um pipe:
❯ echo echo hi | eval "$(cat -)"
hi
Aqui está um exemplo do problema. Algo como o seguinte não será impresso 1
:
❯ echo a=1 | eval "$(cat -)"; echo $a
Teríamos que fazer o seguinte:
❯ echo a=1 | { eval "$(cat -)"; echo $a; }
1
Responder4
Se você não está determinado a usar eval
, use sh
:
cat file.txt | sh
Sim, ele será executado em uma instância sh separada, mas esse fato é autodocumentado.
E também há while read
:
cat file.txt | while read cmd; do eval $cmd; done
Para executar o comando na 5ª linha do arquivo.txt:
sed -n 5p file.txt | sh
(Sei que esta é uma pergunta antiga.)