Por que algumas funções do usuário não são reconhecidas pelo bash?

4

Eu posso definir uma função como:

myfunction () { ls -R "" ; }

E então

myfunction .

apenas funciona.

Mas se eu fizer

echo "myfunction ." | sh
echo "myfunction ." | bash

as mensagens são:

sh: myfunction: not found  
bash: line 1: myfunction: command not found

Por quê? E como eu posso chamar uma função que vem de uma string se não for canalizada para sh ou bash?

Eu sei que existe esse comando source , mas estou confuso sobre quando devo usar source e quando sh ou bash . Além disso, não posso canalizar através de source . Para aumentar a confusão, existe esse comando . que parece não ter nada a ver com o "." isso significa "diretório atual".

    
por Strapakowsky 04.06.2012 / 01:32

3 respostas

7

Uma definição de função só tem um efeito na instância atual do bash. Quando você escreve

echo "myfunction ." | bash

você executa outra instância do bash. Você precisaria definir a função nessa outra instância.

Se você tiver uma string que contenha um nome de função e argumentos (citados, se necessário), ou mais geralmente qualquer string que contenha algum código-fonte de shell que você queira executar, use o eval builtin.

my_snippet='myfunction .'
eval "$my_snippet"

Se você definir funções em seu .bashrc , elas estarão disponíveis apenas em shells interativos, não em scripts.

O comando . é (quase) equivalente a source e não tem nada a ver com . que significa o diretório atual.

    
por Gilles 04.06.2012 / 02:17
8

Em vez de usar eval , você pode usar export da sua função para que ela seja herdada por subshells:

myfunction () { ls -R "" ; }
export -f myfunction

E então

echo "myfunction ." | bash

apenas funciona.

echo "myfunction ." | sh provavelmente não ficará parado, a menos que seu / bin / sh seja um link simbólico para o bash.

    
por glenn jackman 04.06.2012 / 13:07
1

bash e sh esperam que seu argumento seja um arquivo executável, não uma string.

Você pode executar o conteúdo de uma string com

eval "myfunction ."

Quando você executa um programa através do shell, ele normalmente invoca uma nova instância de bash (ou sh , csh , zsh , etc. conforme apropriado), herda todas as configurações do shell original, e execute-se no novo shell. Isso permite que você defina variáveis temporariamente ou altere as configurações sem interferir no seu ambiente.

source ing um comando fará com que ele rode seu shell atual, portanto, quaisquer mudanças que ele fizer no ambiente persistirá quando o comando sair. . é sinônimo de source .

Na maioria das circunstâncias, um script irá especificar em qual shell ele deve ser executado (com #!/bin/bash em sua primeira linha, por exemplo), e não é necessário que você chame o bash explicitamente.

    
por pconley 04.06.2012 / 02:24