Estou bem ciente do utilitário source
(também conhecido como .
), que pega o conteúdo de um arquivo e o executa no shell atual.
Agora, estou transformando algum texto em comandos shell e, em seguida, executando-os, da seguinte maneira:
$ ls | sed ... | sh
ls
é apenas um exemplo aleatório, o texto original pode ser qualquer coisa. sed
também, apenas um exemplo para transformar texto. A parte interessante é sh
. Eu canalizo tudo o que tenho sh
e ele executa.
Meu problema é que isso significa iniciar um novo sub shell. Prefiro que os comandos sejam executados no meu shell atual. Como eu seria capaz de fazer source some-file
se tivesse os comandos em um arquivo de texto.
Não quero criar um arquivo temporário porque parece sujo.
Como alternativa, gostaria de iniciar meu sub shell com as mesmas características do meu shell atual.
atualizar
Ok, as soluções usando crase certamente funcionam, mas geralmente preciso fazer isso enquanto estou verificando e alterando a saída, então eu preferiria que houvesse uma maneira de canalizar o resultado em algo no final.
atualização triste
Ah, a /dev/stdin
coisa parecia tão bonita, mas, em um caso mais complexo, não funcionou.
Então, eu tenho isso:
find . -type f -iname '*.doc' | ack -v '\.doc$' | perl -pe 's/^((.*)\.doc)$/git mv -f $1 $2.doc/i' | source /dev/stdin
O que garante que todos os .doc
arquivos tenham sua extensão em letras minúsculas.
E que, aliás, pode ser resolvido xargs
, mas isso está além do ponto.
find . -type f -iname '*.doc' | ack -v '\.doc$' | perl -pe 's/^((.*)\.doc)$/$1 $2.doc/i' | xargs -L1 git mv
Então, quando eu executar o anterior, ele sairá imediatamente, nada acontece.
Respostas:
$ ls | sed ... | source /dev/stdin
ATUALIZAÇÃO: Funciona no bash 4.0, bem como no tcsh e no traço (se você mudar
source
para.
). Aparentemente, havia erros no bash 3.2. Das notas de lançamento do bash 4.0 :fonte
| bash
fariaeval "$(sed ...)"
abordagem - mas obrigado pelo bug do 3.2!O
eval
comando existe para este propósito.eval "$( ls | sed... )"
Mais do manual do bash :
fonte
eval "$( ssh remote-host 'cat ~/.bash_profile' )"
Observe que estou realmente usando o bash 3.2.Uau, eu sei que essa é uma pergunta antiga, mas me encontrei exatamente com o mesmo problema recentemente (foi assim que cheguei aqui).
De qualquer forma - não gosto da
source /dev/stdin
resposta, mas acho que encontrei uma melhor. Na verdade, é enganosamente simples:echo ls -la | xargs xargs
Legal, certo? Na verdade, isso ainda não faz o que você deseja, porque se você tiver várias linhas, ele as concatará em um único comando em vez de executar cada comando separadamente. Portanto, a solução que encontrei é:
a
-L 1
opção significa que você usa (no máximo) 1 linha por execução de comando. Nota: se sua linha terminar com um espaço final, ele será concatenado com a próxima linha! Portanto, certifique-se de que cada linha termine com um não espaço.Finalmente, você pode fazer
para ver quais comandos são executados (-t é detalhado).
Espero que alguém leia isso!
fonte
Tente usar a substituição de processo , que substitui a saída de um comando por um arquivo temporário que pode ser obtido:
source <(echo id)
fonte
echo <(echo id)
/dev/fd/12
cat <(echo id)
id
source <(echo id)
id
(...)
redirecionado?Acredito que esta seja a "resposta certa" para a pergunta:
ls | sed ... | while read line; do $line; done
Ou seja, pode-se fazer um tubo em um
while
loop; oread
comando comando pega uma linhastdin
dela e a atribui à variável$line
.$line
então se torna o comando executado dentro do loop; e continua até que não haja mais linhas em sua entrada.Isso ainda não funcionará com algumas estruturas de controle (como outro loop), mas se encaixa nesse caso.
fonte
Eu meio que sinto que
ls | sed ... | source -
seria mais bonita, mas infelizmentesource
não entendo o-
que significastdin
.fonte
Acho que sua solução é a substituição do comando com crases: http://tldp.org/LDP/Bash-Beginners-Guide/html/sect_03_04.html
Consulte a seção 3.4.5
fonte
$( )
sintaxe pode ser a preferida. Os backticks do curso funcionam em mais shells ...Para usar a solução do mark4o no bash 3.2 (macos), uma string here pode ser usada em vez de pipelines como neste exemplo:
. /dev/stdin <<< "$(grep '^alias' ~/.profile)"
fonte
Por que não usar
source
então?$ ls | sed ... > out.sh ; source out.sh
fonte