O presente artigo apresenta o comando history do Bash e como ele pode ser utilizado como ferramenta para execução de comandos armazenados no histórico. Ainda, informa como configurar o PS1 para que este exiba a posição em que o comando será armazenado no histórico.

Introdução

Nesta semana eu tive que efetuar o backup de bancos de dados PostgreSQL, armazenados no ambiente de homologação, para a minha máquina de desenvolvimento, buscando encontrar alguns bugs apresentados naquele local. Durante a execução do pg_restore, este apresentou avisos de que não tinha encontrado o usuário utilizado no banco de dados de homologação no desenvolvimento.

Para corrigir o problema, tive que executar 3 comandos distintos, para alterar as permissões em tabelas, visualizações e sequências. O problema é que eu tive que reinstalar o banco de dados inúmeras vezes para encontrar os malditos bugs, sempre executando aqueles 3 comandos através do history.

Acessando o Histórico

O GNU Bash é um shell compatível com sh que está disponível como padrão em muitas distribuições Linux. Facilitando o acesso para execução de programas no sistema operacional por CLI, também fornece comandos internos que facilitam sua utilização, como o cd.

O history é um comando interno ao Bash que fornece ao usuário a possibilidade de visualizar e executar novamente comandos previamente informados. O exemplo abaixo apresenta alguns comandos do dia a dia de qualquer usuário do Bash.

$ mkdir test
$ cd test
$ mkdir one two three
$ touch one/foo two/bar three/baz
$ find . -type f
./two/bar
./three/baz
./one/foo

Ao digitar o comando history, teremos a seguinte saída:

$ history
    1  mkdir test
    2  cd test
    3  mkdir one two three
    4  touch one/foo two/bar three/baz
    5  find . -type f

Como podemos notar, a primeira coluna da saída possui um número sequencial, informando a posição do comando no histórico do Bash. Por sua vez, a segunda coluna possui a saída do comando informado naquele momento. Simples.

Tendo conhecimento desta listagem, o usuário pode solicitar ao Bash a execução do comando touch armazenado na posição 4 através da expansão de histórico !.

$ !4
touch one/foo two/bar three/baz

Também é possível solicitar a execução dos comandos 4 e 5 em sequência.

$ !4; !5
touch one/foo two/bar three/baz; find . -type f
./two/bar
./three/baz
./one/foo

Como o comando ! representa uma expansão no Bash, então podemos utilizá-lo de muitas maneiras como, por exemplo, armazenando-os em arquivos para posterior consulta.

$ echo !4 > command.out
echo touch one/foo two/bar three/baz > command.out
$ cat command.out
touch one/foo two/bar three/baz

Limpeza

O arquivo responsável por armazenar o histórico de comandos encontra-se em ~/.bash_history e sua limpeza pode ser efetuada da seguinte forma.

$ history -c
$ history
    1  history

Consulta Reversa

Como o Bash utiliza a biblioteca readline na compilação, podemos utilizar recursos como o CTRLR para pesquisa reversa no histórico. Ao pressionar esta sequência de teclas e após o conteúdo necessário, será efetuada uma pesquisa reversa no histórico atual. Ao encontrar o comando necessário, basta pressionar a tecla ENTER.

O exemplo abaixo limpa o histórico e executa 3 novos comandos no CLI. Após pressionar CTRLR, efetuar a pesquisa por ls e pressionar a tecla ENTER, teremos executado o comando número 2 novamente.

$ history -c
$ ls -alsh >/dev/null
$ find . | grep one >/dev/null
(reverse-i-search)`ls': ls -alsh >/dev/null

PS1 com Histórico

Também é possível adicionar a posição atual no histórico na variável PS1 do Bash, através da expansão \!. O exemplo abaixo altera o PS1 em tempo de execução, adicionando ao final da linha a posição atual do histórico.

$ history -c
$ PS1="$PS1[\\!] "
$ [2] echo "Hello, World!"
Hello, World!

Note que a expansão necessita do caractere de escape \ na execução, tornando-se \\!. Caso queira alterar o PS1 diretamente no arquivo ~/.bashrc, não há necessidade de inclusão deste caractere.

Conclusão

O Bash é um interpretador de comandos utilizado pelos usuários para execução de programas por CLI. Os comandos informados neste interpretador são registrados e podem ser consultados através do history, incluindo funcionalidades de expansão direta com ! ou consulta reversa implementada pela biblioteca readline.

Por apresentar a simples funcionalidade de execução de comandos, algumas vezes o Bash pode ser pouco estudado pelos usuários, fazendo com que algumas tarefas cotidianas tornem-se tediosas, caso desconheçam estes recursos simples.

Observações

Conforme comentário do leitor Guaracy Monteiro neste artigo, pode-se adicionar rótulos na linha de comando através do caractere hash (#), tratando-os como hashtags para facilitar a pesquisa. O exemplo abaixo apresenta comandos simples com exemplos deste recurso.

$ ls -alsh #list
$ find . -name '*.mp3' #search #mp3
$ touch foobar #reset

Todas as informações após o caractere # serão tratadas como comentários pelo Bash. Porém, estes comentários podem ser encontrados através da consulta reversa e CTRLR. O próximo exemplo apresenta uma possível utilização de consulta de comandos com a hashtag #search.

(reverse-i-search)`#search': find . -name '*.mp3' #search #mp3

Pressionando a sequência de teclas CTRLR e informando o conteúdo de pesquisa #search, encontra-se o comando find para pesquisa de arquivos com a extensão mp3, informado anteriormente com a hashtag da pesquisa.

Referências

Veja Mais