Eu quero habilitar meu histórico de comandos em todas as guias e janelas do terminal para serem gravados .bash_history
definindo PROMPT_COMMAND
em .profile
:
export PROMPT_COMMAND="history -a; history -c; history -r;$PROMPT_COMMAND"
No entanto, quando verifico se essa variável de ambiente já está definida, recebo:
echo $PROMPT_COMMAND
printf "\033]0;%s@%s:%s\007" "${USER}" "${HOSTNAME%%.*}" "${PWD/#$HOME/\~}"
Exportar PROMPT_COMMAND
assim substituirá minha $PROMPT_COMMAND
lista existente ou é necessário prefixar o valor de PROMPT_COMMAND
com um :
antes de exportá-la?
Como um dos principais resultados no google ao pesquisar por
"PROMPT_COMMAND seperator"
, sinto que a resposta merece mais esforço do que o que foi dado até agora.NOTA: Na preparação para este post, testei as versões 3.2, 4.4, 5.0 e 5.1 do Bash (via docker ) e revisei o código-fonte para as mesmas versões (via gnu.org )
Vamos começar ...
Manual(ões) do Bash
Bash <= v5.0
O que isto significa?
Isso significa que o bash faz o equivalente geral de:
Portanto, qualquer encadeamento/sequenciamento de comandos que funcionaria para isso
eval
é permitido.Bash >= v5.1
O que isto significa?
Isso significa que o bash faz o equivalente geral de:
ou seja, cada elemento do array é
eval
'd independentementeO que a comunidade está fazendo
Fazer uma pesquisa
"PROMPT_COMMAND"
no github mostra que:;
como separador$'\n'
como separadorO que eu vi especificamente
Algumas notas anedóticas:
;
(consulte/etc/bashrc_Apple_Terminal
)$'\n'
;
Vamos vê-los em ação
Primeiro, vamos obter um novo ambiente Bash v3.2:
String delimitada por ponto e vírgula
Testar com uma
;
string delimitada por - produz:String delimitada por linha
Testar isso com uma
\n
string -delimitada produz:Misture os dois
Podemos misturar os dois separadores? Yuupp! :
Que tal Arrays?
Para onde estamos indo, precisamos do Bash v5.1
Matriz Literal
Testar isso com uma matriz literal produz:
USANDO OS TRÊS!
E se você misturar todos eles:
Qual usar?
Se
${PROMP_COMMAND}
for um array, você deve anexar/prefixar seu comando ao array.OBSERVAÇÃO Que você pode anexar um grupo de comandos (ou seja, uma cadeia de comandos sing
;
ou$'\n'
delimitada por -) como uma única entrada na matriz, se desejar.Se
${PROMP_COMMAND}
não for uma matriz, você provavelmente deve usar;
ao adicionar seus comandos, pois parece um separador mais oficial, mas saiba que os comandos que você adiciona podem ser scripts mais complexos que podem incluir etapas separadas por$'\n
'.Eu tentaria uma função munging?
Claro !
bash
$PROMPT_COMMAND
(ou cada elemento, se for um array com bash 5.1+, como já observado por @DavidFarrell) é interpretado como código shell, então você escreveria seu conteúdo da mesma forma que escreveria um script de shell. Em um script de shell, os comandos podem ser separados por;
,newline
,|
,&
,&&
,||
, etc, cada um com seu próprio significado.Então você pode ter por exemplo:
etc.
Para anexar um comando a um já definido
$PROMPT_COMMAND
e garantir que ele seja executado independentemente dos anteriores, você tem a opção de;
e newline , mas;
não funcionaria se$PROMPT_COMMAND
estivesse inicialmente vazio ou no caso especial em que termina em um delimitador de documento aqui (como o nossoEOF
acima), assim fazendo:(ou com versões mais antigas:
)
é preferível. Ou:
para antecipá-lo para que seja executado primeiro.
Com o bash 5.1+, você também pode anexar um elemento de matriz:
Ou prefixar:
Isso deixa um problema em potencial: se a opção
errexit
(-e
) estiver habilitada, e qualquer um dos comandos nesses scripts falhar, o processamento para aí¹, então seu comando extra pode acabar não sendo executado. Isso provavelmente deve ser considerado como um caso patológico. Usarerrexit
em um shell interativo provavelmente é uma má ideia (já é bastante controverso quando usado em scripts).Para comparação, em
zsh
, em vez de$PROMPT_COMMAND
, você tem funções de gancho que são chamadas em vários pontos, inspiradas (e aprimoradas) por aliases especiais com nomes semelhantes emtcsh
.precmd()
é a função que você deseja definir para que seja chamada antes de cada prompt. Emzsh
, você também pode definir oprecmd_functions
array especial com funções extras a serem chamadas (errexit
também afeta o processamento lá¹).¹ o mesmo pode acontecer com a
nounset
opção ou se um erro de sintaxe ou qualquer tipo de erro fatal for encontrado durante o processamento.Isso é fácil o suficiente para testar:
Então, a resposta é “não”.
Mas você pode considerá-lo como uma sequência de comandos separada por ponto e vírgula , como qualquer outra linha de código shell:
É isso que a atribuição em sua pergunta tem: um número de comandos, separados por ponto e vírgula, com o valor anterior de
PROMPT_COMMAND
anexado ao final.Claro, outra maneira de executar vários comandos de
PROMPT_COMMAND
, seria criar uma função e chamá-la de lá.Dito isso, a
printf
sequência em seuPROMPT_COMMAND
parece algo que pode ser melhor colocado no prompt real, por dois motivos. Primeiro, ele não termina em uma nova linha, então pode atrapalhar a ideia do Bash de onde o cursor está, assim como outros comandos que produzem linhas incompletas antes de sair. Em segundo lugar, se você tiver o shell reimprimir o prompt, por meio da conclusão de tabulação, será exibido novamentePS1
, masPROMPT_COMMAND
não será executado novamente.