Tentei criar um script echo
'inserindo o conteúdo em um arquivo, em vez de abri-lo com um editor
echo -e "#!/bin/bash \n /usr/bin/command args" > .scripts/command
A saída :
bash:!/bin/bash: evento não encontrado
Eu isolei esse comportamento estranho ao bang .
$ echo !
!
$ echo "!"
bash: !: event not found
$ echo \#!
#!
$ echo \#!/bin/bash
bash: !/bin/bash: event not found
Tente usar aspas simples.
echo -e '#!/bin/bash \n /usr/bin/command args' > .scripts/command
echo '#!'
echo '#!/bin/bash'
O problema está ocorrendo porque o bash está pesquisando em seu histórico!/Bin/bash. O uso de aspas simples evita esse comportamento.
Como Richm disse , o bash está tentando fazer um correspondência de histórico . Outra maneira de evitá-lo é simplesmente escapar do estrondo com um \
:
$ echo \#\!/bin/bash
#!/bin/bash
Embora tenha cuidado com o aspas duplas, o \
não é removido:
$ echo "\!"
\!
!
inicia uma substituição do histórico (um "evento" é uma linha no histórico de comandos); por exemplo !ls
expande para a última linha de comando que contém ls
e !?foo
expande para a última linha de comando que contém foo
. Você também pode extrair palavras específicas (por exemplo, !!:1
refere-se à primeira palavra do comando anterior) e mais; veja o manual para detalhes.
Esse recurso foi inventado para recuperar rapidamente comandos anteriores nos dias em que a edição da linha de comandos era primitiva. Com shells modernos (pelo menos bash e zsh) e copiar e colar, a expansão do histórico não é tão útil quanto costumava ser - ainda é útil, mas você pode sobreviver sem ele.
Você pode alterar qual caractere aciona a substituição do histórico definindo a variável histchars
; se você raramente usa a substituição do histórico, pode definir por ex. histchars='¡^'
de modo a ¡
aciona a expansão do histórico em vez de !
. Você pode até desativar o recurso completamente com set +o histexpand
.
Para poder desativar a expansão do histórico em uma linha de comando específica, você pode usar space
como o terceiro caractere de $histchars
:
histchars='!^ '
Então, se você digitar seu comando com um espaço à esquerda, a expansão do histórico não será executada.
bash-4.3$ echo "#!/bin/bash"
bash: !/bin/bash: event not found
bash-4.3$ echo "#!/bin/bash"
#!/bin/bash
Observe, no entanto, que os espaços iniciais também são usados quando $HISTCONTROL
contém ignorespace
como uma maneira de informar bash
para não registrar uma linha de comando no histórico.
Se você deseja que os dois recursos sejam independentes, precisará escolher outro caractere como o terceiro caractere de $histchars
. Você quer um que não afete a maneira como seu comando é interpretado. Algumas opções:
\
): \echo foo
funciona, mas tem o efeito colateral de desativar aliases ou palavras-chave.se você não se importa em digitar duas teclas, pode escolher qualquer caractere que normalmente não aparece na primeira posição (%
, @
, ?
, escolha o seu) e crie um alias vazio para ele:
histchars='!^%'
alias %=
Em seguida, insira esse caractere, espaço e seu comando:
bash-4.3$ % echo !!
!!
(você não poderá gravar um comando em que a substituição do histórico foi desativada. Observe também que o terceiro caractere padrão de $histchars
é #
para que a expansão do histórico não seja feita nos comentários. Se você o alterar e inserir comentários no Prompt, esteja ciente do fato de que! seqüências podem ser expandidas para lá).
As soluções propostas não funcionam, por exemplo, no exemplo a seguir:
$ bash -c "echo 'hello World!'"
-bash: !'": event not found
$
Nesse caso, o estrondo pode ser impresso usando seu código octal ASCII:
$ bash -c "echo -e 'hello World\0041'"
hello World!
$
Uma solução simples ainda não mencionada é usar uma variável:
$ var='!'
$ echo -e "#${var}/bin/bash \n /usr/bin/command args" > .scripts/command
Imprimindo um bang!
é não um problema quando a string não está entre aspas ou está entre aspas simples ou dentro de uma C-String
$ echo hi\!pal 'hi!pal' $'hi!pal'
hi!pal 'hi!pal' $'hi!pal'
Também não é um problema quando o histexpand está desabilitado (shopt -ou histexpand
ou set +o histexpand
ou simplesmente set +H
. Também é possível alterar os caracteres de expansão e facilitar a impressão de um bang!
.
Mas a solução mais simples portátil é: use um var
$ var='!'
$ echo "hi${var}pal"
hi!pal