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: 16 de junho de 2020
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 feita 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:
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
;
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ês devem
usar a opção --color=none
, se nã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.
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 |
Acabou! Foi bom para mim, foi bom para você também? :)
Error: No site found with the domain 's2.dicas-l.com.br' (Learn more)