Usando o XARGS

  • Post author:
  • Post category:Sem categoria

Este artigo foi adquirido pelo site Dicas-L da Unicamp

Colabora??o: J?lio Neves

Apesar de hoje ser dia de praia/piscina e cerveja gelada, vou pegar pesado porque a nossa semana de dicas est? acabando e eu n?o poderia deixar de mostrar as op??es e seus respectivos usos do comando xargs.

Existe um comando, cuja fun??o primordial ? construir listas de par?metros e pass?-la para a execu??o de outros programas ou instru??es. Este comando ? o xargs e deve ser usado da seguinte maneira:

xargs [comando [argumento inicial]]

Caso o comando, que pode ser inclusive um script Shell, seja omitido, ser? usado por default o echo.

O xargs combina o argumento inicial com os argumentos recebidos da entrada padr?o, de forma a executar o comando especificado uma ou mais vezes.

Exemplo:

Vamos produrar em todos os arquivos abaixo de um determinado diret?rio uma cadeia de caracteres usando o comando find com a op??o type f para pesquisar somente os arquivos normais, desprezando diret?rios, arquivos especiais, arquivos de liga??es, etc, e vamos torn?-la mais gen?rica recebendo o nome do diret?rio inicial e a cadeia a ser pesquisada como par?metros. Para isso fazemos:

$ cat grepr
#
# Grep recursivo
# Pesquisa a cadeia de caracteres definida em $2 a partir do diretorio $1
#
find $1 -type f -print|xargs grep -l “$2”

Na execu??o deste script procuramos, a partir do diret?rio definido na vari?vel $1, todos os arquivos que continham a cadeia definida na vari?vel $2.

Exatamente a mesma coisa poderia ser feito se a linha do programa fosse a seguinte:

find $1 -type f -exec grep -l “$2” {} \;

Este processo tem duas grandes desvantagens sobre o anterior:

1. A primeira ? bastante vis?vel: o tempo de execu??o deste m?todo ? muito superior ao daquele, isso porque o grep ser? feito em cada arquivo que lhe for passado pelo find, um-a-um, ao passo que com o xargs, ser? passada toda, ou na pior das hip?teses, a maior parte poss?vel, da lista de arquivos gerada pelo find;

2. Dependendo da quantidade de arquivos encontrados que atendem ao find, poderemos ganhar aquela famosa e fat?dica mensagem de erro “Too many arguments” indicando um estouro da pilha de execu??o do grep. Como foi dito no item anterior, se usarmos o xargs ele passar? para o grep a maior quantidade de par?metros poss?vel, suficiente para n?o causar este erro, e caso necess?rio executar? o grep mais de uma vez.

ATEN??O! A? pessoal do linux que usa o ls colorido que nem porta de tinturaria: nos exemplos a seguir que envolvem esta instru??o, voc? devem usar a op??o –color=none, sen?o existem grandes chances dos resultados n?o ocorrerem como o esperado.

Vamos agora analisar um exemplo que ? mais ou menos o inverso deste que acabamos de ver. Desta vez, vamos fazer um script para remover todos os arquivos do diret?rio corrente, pertencentes a um determinado usu?rio.

A primeira id?ia que surge ?, como no caso anterior, usar um comando find, da seguinte maneira:

$ find . -user cara -exec rm -f {} \;

Quase estaria certo, o problema ? que desta forma voc? removeria n?o s? os arquivos do cara no diret?rio corrente, mas tamb?m de todos os outros subdiret?rios “pendurados” neste. Vejamos ent?o como fazer:

$ ls -l | grep ” cara ” | cut -c55- | xargs rm

Desta forma, o grep selecionou os arquivos que continham a cadeia cara no diret?rio corrente listado pelo ls -l. O comando cut pegou somente o nome dos arquivos, passando-os para a remo??o pelo rm usando o comando xargs como ponte.

mais xargs

Colabora??o: J?lio Neves

Continuamos hoje o que come?amos ontem, isto ?, a ver as facilidades oferecidas pelo comando xargs.

O xargs ? tamb?m uma excelente ferramenta de cria??o de one-liners (scripts de somente uma linha). Veja este para listar todos os donos de arquivos (inclusive seus links) “pendurados” no diret?rio /bin e seus subdiret?rios.

$ find /bin -type f -follow | \
xargs ls -al | tr -s ‘ ‘ | cut -f3 -d’ ‘ | sort -u

Muitas vezes o /bin ? um link (se n?o me engano, no Solaris o ?) e a op??o -follows obriga o find a seguir o link. O comando xargs alimenta o ls -al e a seq??ncia de comandos seguinte ? para pegar somente o 3? campo (dono) e classific?-lo devolvendo somente uma vez cada dono (op??o -u do comando sort).

Voc? pode usar as op??es do xargs para construir comandos extremamente poderosos. Para exemplificar isso e come?ar a entender as principais op??es desta instru??o, vamos supor que temos que remover todos as arquivos com extens?o .txt sob o diret?rio corrente e apresentar os seus nomes na tela. Veja o que podemos fazer:

$ find . -type f -name “*.txt” | \
xargs -i bash -c “echo removendo {}; rm {}”

A op??o -i do xargs troca pares de chaves ({}) pela cadeia que est? recebendo pelo pipe (|). Ent?o neste caso as chaves ({}) ser?o trocadas pelos nomes dos arquivos que satifa?am ao comando find.

Olha s? a brincadeira que vamos fazer com o xargs:

$ ls | xargs echo > arq.ls
$ cat arq.ls
arq.ls arq1 arq2 arq3
$ cat arq.ls | xargs -n1
arq.ls
arq1
arq2
arq3

Quando mandamos a sa?da do ls para o arquivo usando o xargs, comprovamos o que foi dito anteriormente, isto ?, o xargs manda tudo que ? poss?vel (o suficiente para n?o gerar um estouro de pilha) de uma s? vez. Em seguida, usamos a op??o -n 1 para listar um por vez. S? para dar certeza veja o exemplo a seguir, quando listaremos dois em cada linha:

$ cat arq.ls | xargs -n 2
arq.ls arq1
arq2 arq3

Mas a linha acima poderia (e deveria) ser escrita sem o uso de pipe (|), da seguinte forma:

$ xargs -n 2 < arq.ls Outra op??o legal do xargs ? a -p, na qual o xargs pergunta se voc? realmente deseja executar o comando. Digamos que em um diret?rio voc? tenha arquivo com a extens?o .bug e .ok, os .bug est?o com problemas que ap?s corrigidos s?o salvos como .ok. D? uma olhadinha na listagem deste diret?rio: $ ls dir
arq1.bug
arq1.ok
arq2.bug
arq2.ok

arq9.bug
arq9.ok

Para comparar os arquivos bons com os defeituosos, fazemos:

$ ls | xargs -p -n2 diff -c
diff -c arq1.bug arq1.ok ?…y
….
diff -c arq9.bug arq9.ok ?…y

Para finalizar, o xargs tamb?m tem a op??o -t, onde vai mostrando as instru??es que montou antes de execut?-las. Gosto muito desta op??o para ajudar a depurar o comando que foi montado.

Ent?o podemos resumir o comando de acordo com a tabela a seguir:

Op??o A??o

-i Substitui o par de chaves ({}) pelas cadeias recebidas
-nNum Manda o m?ximo de par?metros recebidos, at? o m?ximo de Num para o comando a ser executado
-lNum Manda o m?ximo de linhas recebidas, at? o m?ximo de Num para o comando a ser executado
-p Mostra a linha de comando montada e pergunta se deseja execut?-la
-t Mostra a linha de comando montada antes de execut?-la

Duvidas? [email protected]
Deseja fazer curso de Programa??o em Shell? [email protected]