-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA256
Jaboatão dos Guararapes, PE, Brasil, 21 de maio de 2015.
Eis uma tradução livre do artigo divulgado por Avishek Kumar.
Disponível em:
<http://www.tecmint.com/mysterious-uses-of-symbol-or-operator-in-linux-commands/>.
Acesso em: 21 maio 2015.
10 Incríveis e Misteriosos Usos do Símbolo ou Operador (!) nos Comandos
Linux
por Avishek Kumar
Atualização mais recente: 18 maio 2015
O símbolo ou operador "!" no Linux pode ser utilizado como operador
Lógico de Negação bem como para recuperar comandos do histórico com
truques ou para executar comandos previamente executados com
modificação. Todos os comandos abaixo foram verificados
explicitamente no Shell bash. Apesar de eu não ter verificado, mas
a maior parte deles não funcionará em outro shell. Aqui vamos nós
para os incríveis e misteriosos usos do símbolo ou operador "!" nos
comandos Linux.
1. Execute um comando a partir do histórico pelo número do comando.
Você pode não estar consciente do fato de que você pode executar um
comando a partir do seu histórico de comandos (comandos já/antes
executados). Para começar, primeiro encontre o número do comando
executando o comando "history".
$ history
Agora execute um comando a partir do histórico simplesmente pelo
número pelo qual o comando é listado, na saída do comando "history".
Digamos execute um comando que aparece no número 1551 na saída do
comando "history".
$ !1551
E, o comando é executado (o comando "top" no caso), o qual foi
listado no número 1551. Essa forma de recuperar um comando já
executado é muito útil especialmente no caso daqueles comandos que
são longos. Você simplesmente precisa chamá-lo utilizando ![Número
no qual o comando aparece na saída do comando "history"].
- ------------------------------
- ------------------------------
2. Execute um comando previamente executado como o 2º comando mais
recente, 7º comando mais recente, etc.
Você pode executar aqueles comandos que você executou previamente
pela sequência de execução deles, sendo que o comando executado mais
recentemente será representado como -1; o segundo mais recente como
-2; o sétimo mais recente como -7.
Primeiro execute o comando "history" para obter uma lista dos
comandos executados mais recentemente. É obrigatório executar o
comando "history", de forma que você pode ter certeza de que não
existe um comando como o comando "rm arquivo" e outros simplesmente
para ter certeza de que você não está executando qualquer comando
perigoso acidentalmente. E então verifique o Sexto comando mais
recente, o Oitavo comando mais recente e o Décimo comando mais
recente.
$ history
$ !-6
$ !-8
$ !-10
- ------------------------------
- ------------------------------
3. Passe argumentos do comando mais recente que nós executamos para o
novo comando sem redigitar
Eu preciso listar o conteúdo do diretório
"/home/$USER/Binary/firefox", então eu disparo.
$ ls /home/$USER/Binary/firefox
Então eu percebo que eu deveria ter disparado "ls -l" para ver qual
arquivo é executável? Então eu deveria digitar o comando inteiro
outra vez! Não, eu não preciso. Eu preciso simplesmente carregar
o último argumento para este novo comando assim:
$ ls -l !$
Aqui "!$" carregará argumentos passados no último comando para esse
novo comando.
- ------------------------------
- ------------------------------
4. Como manipular dois ou mais argumentos utilizando (!)
Digamos que eu criei um arquivo de texto chamado "1.txt" na Área de
Trabalho.
$ touch /home/avi/Desktop/1.txt
e então eu copio ele para "/home/avi/Downloads" utilizando o caminho
completo em ambos os lados com o comando "cp".
$ cp /home/avi/Desktop/1.txt /home/avi/downloads
Agora nós passamos dois argumentos com o comando "cp". O primeiro
argumento é "/home/avi/Desktop/1.txt" e o segundo é
"/home/avi/downloads". Vamos manipulá-los diferentemente,
simplesmente execute "echo [argumentos]" para imprimir ambos os
argumentos diferentemente.
$ echo “1st Argument is : !^”
$ echo “2nd Argument is : !cp:2”
Perceba que o 1º argumento pode ser impresso como “!^” e o restante
os argumentos podem ser impressos executando
“![Name_of_Command]:[Number_of_argument]”.
No exemplo acima, o primeiro comando foi "cp" e o 2º argumento foi
necessário para se imprimir. Dado “!cp:2”, se qualquer comando,
digamos "xyz", for executado com 5 argumentos e você precisa do 4º
argumento, você pode utilizar “!xyz:4”, e utilizá-lo como quiser.
Todos os argumentos podem ser acessados via “!*”.
- ------------------------------
- ------------------------------
5. Execute o comando mais recente na base de palavras-chave
Nós podemos executar o comando mais recentemente executado na base de
palavras-chave. Podemos entender as palavras-chave conforme a
seguir:
$ ls /home > /dev/null [Command 1]
$ ls -l /home/avi/Desktop > /dev/null [Command 2]
$ ls -la /home/avi/Downloads > /dev/null [Command 3]
$ ls -lA /usr/bin > /dev/null [Command 4]
Aqui nós utilizamos o mesmo comando (ls), mas com diferentes
modificadores e para diferentes diretórios. Além disso, nós
enviamos a saída de cada comando para "/dev/null", uma vez que não
vamos lidar com a saída do comando, o que também mantém o console
limpo.
Agora, execute o comando mais recentemente executado na base de
palavras-chave.
$ ! ls [Command 1]
$ ! ls -l [Command 2]
$ ! ls -la [Command 3]
$ ! ls -lA [Command 4]
Verifique a saída e você ficará atônito, pois você está executando
comandos já executados simplesmente por palavras-chave do "ls".
- ------------------------------
- ------------------------------
6. O poder do Operador !!
Você pode executar/alterar o seu comando mais recentemente executado
utilizando (!!). Isso chamará o comando mais recentemente executado
com alterações/modificações no comando atual. Vamos te mostrar o
cenário.
Ontem eu executei um script de uma linha para obter o meu número IP
privado, então eu executei:
$ ip addr show | grep inet | grep -v 'inet6'| grep -v '127.0.0.1' | awk '{print $2}' | cut -f1 -d/
Então, repentinamente, eu percebi que eu preciso redirecionar a saída
do scrip acima para um arquivo ip.txt, então o que eu deveria fazer?
Eu deveria redigitar o comando inteiro novamente e redirecionar a
saída para um arquivo? Bem, uma solução simples é utilizar a tecla
de navegação UP e adicionar "> ip.txt" para redirecionar a saída para
um arquivo, como:
$ ip addr show | grep inet | grep -v 'inet6'| grep -v '127.0.0.1' | awk '{print $2}' | cut -f1 -d/ > ip.txt
Agradeça à tecla de navegação UP salvadora de vida aqui. Agora,
considere a condição abaixo, a próxima vez que eu executar o scrip de
uma linha abaixo.
$ ifconfig | grep "inet addr:" | awk '{print $2}' | grep -v '127.0.0.1' | cut -f2 -d:
Tão logo eu execute o script, o prompt do bash retornou um erro com a
mensagem:
“bash: ifconfig: comando não encontrado”
Não foi difícil para mim perceber que eu executei esse comando como
um usuário comum, onde ele deveria ter sido executado como usuário
root.
Então, qual é a solução? É difícil se logar como usuário "root" e
então digitar o comando inteiro novamente! Também (a Tecla de
Navegação UP) no exemplo mais recente não veio salvar aqui. Então?
Nós precisamos chamar “!!” sem as aspas, o qual chamará o comando
mais recente para aquele usuário.
$ su -c “!!” root
Aqui "su" é "switch user" - "permuta usuário" - o qual usuário é
"root", "-c" é para executar o comando específico como o usuário e a
parte mais importante "!!" será substituída por "comando" e o comando
mais recentemente executado será substituído aqui. Isso! Você
precisa fornecer a senha do usuário "root".
Eu faço uso do "!!" a maioria nos cenários seguintes:
1. Quando eu executo o comando "apt-get" como usuário normal, eu
normalmente recebo um erro dizendo que você não tem permissão para
executar.
$ apt-get upgrade && apt-get dist-upgrade
Opa! não se preocupe! execute o comando abaixo para fazê-lo com
sucesso:
$ su -c !!
Da mesma maneira eu faço para:
$ service apache2 start
ou
$ /etc/init.d/apache2 start
ou
$ systemctl start apache2
Oops! Usuário não autorizado a carregar tal tarefa, então eu executo:
$ su -c 'service apache2 start'
ou
$ su -c '/etc/init.d/apache2 start'
ou
$ su -c 'systemctl start apache2'
- ------------------------------
- ------------------------------
7. Execute um comando que afeta todos os arquivos, exceto
![NOME_ARQUIVO]
O "!" (NÃO Lógico) pode ser utilizado para executar o comando sobre
todos os arquivos/extensões, exceto aqueles atrás de "!".
A. Remova todos os arquivos de um diretório, exceto aquele cujo nome
é "2.txt".
$ rm !(2.txt)
B. Remova todos os arquivos do tipo de um diretório, exceto aquele
cuja extensão é "pdf".
$ $ rm !(*.pdf)
- ------------------------------
- ------------------------------
8. Verificar se um diretório (digamos "/home/avi/Tecmint") existe ou
não? Se o dito diretório existe ou não, imprima uma mensagem com o
comando "printf"
Aqui nós utilizaremos "! -d" para validar se o diretório existe ou
não, seguido pelo Operador Lógico AND (&&) para imprimir caso aquele
diretório não exista; e o Operador Lógico OR (||) para imprimir caso
o diretório esteja presente.
A lógica é: quando a saída de [ ! -d /home/avi/Tecmint ] for 0
(zero), será executado aquilo que pertence ao Operador Lógico AND; do
contrário, a execução irá para o Operador Lógico OR (||) e executa
aquilo que pertencer ao Operador Lógico OR.
$ [ ! -d /home/avi/Tecmint ] && printf '\nnão existe o tal diretório /home/avi/Tecmint\n' || printf '\nexiste o diretório /home/avi/Tecmint\n'
- ------------------------------
- ------------------------------
9. Verificar se um diretório existe ou não? Se não, sair do comando.
Semelhante à condição acima, mas aqui se o diretório desejado não
existir, a execução saíra do comando.
$ [ ! -d /home/avi/Tecmint ] && exit
- ------------------------------
- ------------------------------
10. Criar um diretório (digamos "teste") no seu diretório "home", caso
ele já não exista.
Uma implementação geral em Linguagem de Script onde se o diretório
desejado não existir, a execução criará um.
[ ! -d /home/avi/Tecmint ] && mkdir /home/avi/Tecmint
- ------------------------------
- ------------------------------
Por enquanto é isso. Se você souber ou descobrir qualquer outro
uso de "!" o qual valha a pena saber, você pode desejar nos fornecer
a sua sugestão em feedback. Mantenha-se conectado!
1. Edgar Allen says:
May 19, 2015 at 10:30 pm
Você também pode mencionar "!?"
Isso encontra o comando mais recente com o argumento string dele.
Por exemplo, se ...
1013 grep tornado /usr/share/dict/words
1014 grep hurricane /usr/share/dict/words
1015 wc -l /usr/share/dict/words
estão todos no histórico, então "!?torn" pesquisará por tornado
novamente, onde "!torn" procuraria em vão por um comando iniciando
com "torn".
E "wc !?torn?:2" funciona para selecionar o argumento dois do
comando contendo "tornado" e executar um "wc" sobre ele.
Resposta:
+ Avishek Kumar says:
May 20, 2015 at 11:25 am
Caro Edgar,
Sua sugestão foi levada em conta.
Obrigado pelo seu feedback.
2. Stephen says:
May 19, 2015 at 6:07 pm
Eu não vi uma menção do contexto histórico no artigo, então eu
darei algum aqui nos comentários. Essa forma de substituição
de histórico de comando originou-se com o Shell C (csh), criado
por Bill Joy para o sabor BSD de UNIX, lá no começo dos anos 70.
Mais tarde foi incorporado no tcsh, e bash (Bourne-Again SHell).
Pessoalmente, eu sempre tenho preferido o mecanismo de
substituição de histórico do C-shell, e nunca realmente olhei
para o comando "fc" (o qual eu encontrei primeiramente no Korne
shell).
Resposta:
+ Avishek Kumar says:
May 20, 2015 at 11:27 am
Caro Stephen,
Obrigado pelo pedaço maravilhoso de informação. Mantenha-se
conectado e nos mantenha ciente de tal contexto.
3. suzy says:
May 16, 2015 at 11:45 am
4º comando. Você pode acessá-lo muito mais simplesmente. Existem
atualmente expressões regulares:
^ está no começo da expressão
$ está no fim da expressão
:number qualquer parâmetro de número
Exemplo:
touch a.txt b.txt c.txt
echo !^ –> exibe o primeiro parâmetro
echo !:1 –> também exibe o primeiro parâmetro
echo !:2 –> exibe o segundo parâmetro
echo !:3 –> exibe o terceiro parâmetro
echo !$ –> exibe o último (no nosso caso, o 3º) parâmetro
echo !* –> exibe todos os parâmetros
Resposta:
+ Avishek Kumar says:
May 18, 2015 at 11:30 pm
E nós dissemos o mesmo:
echo “1st Argument is : !^”
$ echo “2nd Argument is : !cp:2”
echo seguido do 1º argumento e 2º argumento é simplesmente tornar
o tutorial e comando ininteligível. Eu tenho utilizado "!^".
"!command:number" como você está sugerindo.
Eu gostaria de saber se você quer dizer algo diferente?
4. Tomasz Wiszkowski says:
May 16, 2015 at 10:50 am
Eu penso (5) funciona diferentemente do que você anotou, e o
redirecionamento para /dev/null escondeu, porém ZSh ainda
imprime o comando. Quando você invoca “! ls…”, sempre pega o
comando "ls" mais recente que você executou, simplesmente acrescenta
seus modificadores ao final (depois /dev/null). Uma coisa extra legal
é o operador "!#", o qual pega argumentos da linha atual. Particularmente
bom se você precisa redigitar nomes de caminho longos que você já digitou
na linha atual. Simplesmente digamos, por exemplo
cp /some/long/path/to/file.abc !#:1
E pressione "tab". Isso vai substituir o último argumento com o nome do
arquivo e caminho inteiro.
Resposta:
+ Avishek Kumar says:
May 18, 2015 at 11:37 pm
Tomasz,
Para a sua primeira parte do feedback: não pega o comando executado
mais recentemente e simplesmente para provar isso nós utilizamos 4
modificadores diferentes para o mesmo comando.
($ ! ls $ ! ls -l $ ! ls -la $ ! ls -lA ). Agora você pode verificar
isso fornecendo as palavras-chave em qualquer ordem e em qualquer caso
será exibido o mesmo resultado. Mesmo que isso não esteja funcionando
no ZSH como esperado, eu já mencionei que eu testei no BASH e a maioria
deles pode não funcionar em outro shell.
Para a segunda parte, o que você mencionou é uma HASH TAG na Linha de
Comando do Linux e nós incluímos em um dos nossos artigos. Você pode
desejar lê-lo aqui: http://www.tecmint.com/linux-commandline-chat-server-and-remove-unwanted-packages/
5. Manu says:
May 16, 2015 at 8:55 am
Artigo legal.
Resposta:
+ Avishek Kumar says:
May 18, 2015 at 11:30 pm
Seja bem vindo Manu, Mantenha-se conectado!
6. Tachyon says:
May 16, 2015 at 4:40 am
Grande post. Obrigado, eu recompartilhei para G+
Uma nota, "su" significa "switch user" e não "Suitable User".
Nota menor. Pelo menos isso ainda é representativo do que
atualmente faz, diferente do que a maior parte das pessoas
refere-se como "Super User", pensando que o comando concede
apenas status de usuário "root", o que é absolutamente
incorreto.
Resposta:
+ Ravi Saive says:
May 18, 2015 at 11:08 am
@Tachyon,
obrigado corrigido no texto acima..
Jamenson Ferreira Espindula de Almeida Melo
Usuário GNU/Linux nº 166197
https://linuxcounter.net/cert/166197.png
Impressão digital da chave:
234D 1914 4224 7C53 BD13 6855 2AE0 25C0 08A8 6180
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v2.0.26 (GNU/Linux)
iQEcBAEBCAAGBQJVXmQhAAoJECrgJcAIqGGA5xIIAKfXnn8D75spCHUhuESdz/6w
GiPFOOb9YQu7Ha22giyVozw8oTTLf99s5ObM6cg1omj6g5ogjbwW7LUgMFe88taH
O0EnWwCfiFtHx2zoEY8/wI56twILSCgr+9oMl3BQMzlgyTuSXnrMRzUbtR5SVLZy
z204ignWQfuUfVA7OqEq3CZRvpX+sKas2t88LuW/2kYWE4Nc3w6VVE/uACn5Q/Pg
75DcppcDTavB2jjGmwahg0jKtagcN+bYCUFSu0YBHDbkniXKkDDqbevD0RsheNoT
+Jp5E2oybTFce/eFz4Gqr6f0Z6Uje7+4iXSGd68fJbgUUTv//06ShxGF2TjKCY0=
=CbfT
-----END PGP SIGNATURE-----
Nenhum comentário:
Postar um comentário