De acordo com as Leis 12.965/2014 e 13.709/2018, que regulam o uso da Internet e o tratamento de dados pessoais no Brasil, ao me inscrever na newsletter do portal DICAS-L, autorizo o envio de notificações por e-mail ou outros meios e declaro estar ciente e concordar com seus Termos de Uso e Política de Privacidade.
Colaboração: Julio Cezar Neves
Data de Publicação: 15 de agosto de 2019
Eu quero listar todos os arquivos com os nomes começados por arq
de um
diretório, contando-os, então eu faço:
ls arq* | while read Arq do echo $((i)) $Arq done; echo Eu tenho :$i: arquivos
E a saída disso foi a seguinte:
1 arq
2 arq.err
3 arq.err1
4 arq.limpo
5 arq.lixo
6 arq.log
7 arq10
Eu tenho :: arquivos
Ou seja, funcionou tudo beleza, mas na hora de totalizar deu caca. Você sabe por quê? Explico: o while
inteiro rodou num subshell provocado pelo pipe (|
) e como você pode ver pela contagem, a variável $i
foi incrementada, mas ao terminar o subshell, todo seu ambiente foi embora com ele e $i
não escapou.
Como fazer então? Se fosse um arquivo que eu estivesse listando, bastaria redirecionar a entrada do loop com um < ARQUIVO
logo após o done
. Mas o ls
não é um arquivo, é um comando, então o que fazer? É para isso que existe a substituição de processos, então você deveria fazer:
while read Arq do echo $((i)) $Arq done < <(ls); echo Eu tenho :$i: arquivos
onde o 1º menor (<
) é o redirecionamento de entrada (stdin) e o <(ls)
é a Substituição de Processos.
Veja isso:
cat <(ls arq*)
arq
arq.err
arq.err1
arq.limpo
arq.lixo
arq.log
arq10
Se o cat
listou é porque o <(ls arq*)
é um arquivo. Então vamos inverter isso para que ver que arquivo é esse:
Disso tudo que vimos até agora, podemos resumir dizendo que a Substituição de Processos é uma técnica na qual se emula a saída de um comando como vindo de um arquivo temporário do tipo FIFO ou Named Pipe e serve para uso em instruções que precisam de um arquivo como entrada.
Como um exemplo final, vejamos o comando comm
, muito pouco usado, porém excelente no que se propõe. Sua sintaxe é:
comm [OPCOES]... ARQ1 ARQ2
e ele é usado para comparar linha a linha ARQ1
e ARQ2
, desde que estejam classificados
Sem nenhuma opção ele produz uma saída com 3 colunas:
ARQ1
ARQ2
Mas as suas principais opções são:
-1 |
Suprime a coluna 1 |
-2 |
Suprime a coluna 2 |
-3 |
Suprime a coluna 3 |
Uma vez entendido o comando, voltemos à Substituição de Parâmetros: o problema era excluir todos os arquivos que não tivessem uma determinada palavra. Veja o one-liner solução:
$ rm -i $(comm -13 <(grep -li 'PALAVRA' *) <(ls))
Nesta linha o comando rm -i
removerá interativamente a saída do comando:
comm -13 <(grep -li 'PALAVRA' *) <(ls)
Que nada mais é que a instrução comm
comparando 2 arquivos do tipo Named Pipe:
<(grep -li 'PALAVRA' *) |
Que devolve o nome (-l ) de todos os arquivos que contêm PALAVRA e |
<(ls) |
O nome de todos os arquivos. |
Com a opção -13
, são suprimidas as colunas 1 e 3, sobrando unicamente a coluna 2 que é referente às linhas únicas do arquivo 2, isto é, aqueles nos quais não foi encontrado PALAVRA.
Espero que este artigo tenha sido útil para entender o funcionamento da Substituição de Processos e, de quebra, os macetes do utilíssimo comando comm
.
This policy contains information about your privacy. By posting, you are declaring that you understand this policy:
This policy is subject to change at any time and without notice.
These terms and conditions contain rules about posting comments. By submitting a comment, you are declaring that you agree with these rules:
Failure to comply with these rules may result in being banned from submitting further comments.
These terms and conditions are subject to change at any time and without notice.
Comentários