Arquivo da tag: awk

Shell script e cacls

O problema: um colega de trabalho queria checar as permissões de acesso de uma grande árvore de pastas em um servidor Windows. Muitos níveis de subpastas e permissões diferentes em cada uma. Por grande árvore de pastas, entenda por volta de umas 43000 pastas.
Eu não sei dizer se tem ferramenta mais fácil pra fazer o que ele queria, ou se um script VBS poderia resolver; eu até sugeri VBS, mas nenhum de nós dois conhecíamos o suficiente e aprender para resolver o problema iria tomar algum tempo. Então, ele e eu tomamos rotas usando ferramentas já conhecidas. Ele queria gerar uma saída de texto de cada pasta, usando o comando cacls do Windows, que permite listar e alterar as permissões via linha de comando. A saída desse comando é similar a isto:

Os nomes foram trocados para preservar os personagens.

Os nomes foram trocados para preservar os personagens.


Ou seja: o nome completo da pasta em questão, seguido das permissões. Havendo mais de uma permissão, elas aparecerão nas linhas seguintes, identadas com espaços para ficarem na mesma coluna que a primeira permissão listada (cuja coluna dependerá do tamanho do nome da pasta/arquivo listado).
Meu colega me perguntou se tinha alguma forma de rodar estas saídas em um script de forma a acrescentar o nome de pasta a cada uma das permissões subsequentes, de forma a facilitar a verificação; por exemplo, a listagem acima ficaria assim (usando : para separar nomes de pasta, de usuário/grupos e permissões):
\\stgreceita1\rfoc$\compartilhamentos\OC\DIESP\DIJUT\18 Controle de PL:BUILTIN\Administradores:(OI)(CI)F
\\stgreceita1\rfoc$\compartilhamentos\OC\DIESP\DIJUT\18 Controle de PL:RFOC\Domain Admins:(OI)(CI)R
\\stgreceita1\rfoc$\compartilhamentos\OC\DIESP\DIJUT\18 Controle de PL:RFOC\LS_COMP_DIESP_R:(OI)(CI)R
\\stgreceita1\rfoc$\compartilhamentos\OC\DIESP\DIJUT\18 Controle de PL:AUTORIDADE NT\SYSTEM:(OI)(CI)F

Solução: tentei fazer de cara com o sed, tentando descobrir uma forma de pegar tudo o que aparecia na linha antes do último espaço e repetir nas demais linhas, substituindo os espaços da linha; mas acabei ficando com este two-liner que deu conta do recado:
caminho=$(cat arq.txt | awk '(NR==1) { printf $1; for(i=2; i<nf ; i++) { printf " "; printf $i } }' | tr '\\' '/')
cat arq.txt | sed 's/acesso especial/acesso_especial/' | awk "{ print \"$caminho\:\"\$NF }" | tr '/' '\\' >> saida.txt

Sendo arq.txt o arquivo que contém a saída do cacls para uma pasta, e saida.txt o arquivo de saída. Depois bastou criar um loop para executar esses dois comandos para cada arquivo de entrada e pronto.
O primeiro comando pega o caminho da pasta, lendo apenas a primeira linha do arquivo e capturando tudo até o último espaço; depois esse caminho é acrescentado pelo segundo comando no começo de cada linha, retirando os espaços de identação. O sed da segunda linha está lá apenas para tratar o caso do texto “acesso especial”, que contém um espaço e atrapalhava o funcionamento do awk seguinte.
Como disse, pode ser que uma linguagem de script já própria do Windows como VBS ou Powershell resolvesse o problema de forma mais simples, mas como meu colega queria uma solução rápida resolvemos desta forma. Conhecer um pouco de shell e ter um cygwin instalado na máquina Windows ajudou bastante 😉

Extraindo o último elemento de uma linha com o awk

awk, o mastigador de linhas de texto

awk, o mastigador de linhas de texto

Hoje surgiu a necessidade de manipular, via script (shell), um arquivo texto e pegar o último elemento de uma linha, que é um código. Como a linha de exemplo abaixo:

DISSE0074I Operation successfully submitted. Distribution ID is 1234567890.123456.

No caso eu preciso pegar o código numérico no fim da linha. Geralmente eu usaria apenas o comando cut, como: cut -d’ ‘ -f8, mas e se a mensagem variar de tamanho (quantidade de palavras)? Como saber o índice do último elemento?
Entra em ação o awk. Usando awk ‘{print $8}’ dá pra imprimir o elemento número 8; e há a variável NF que informa a quantidade de campos. Então dá pra extrair o último campo assim:

cat arquivo.txt | awk ‘{print $NF}’

Perfeito para o que eu queria.