Usando o diff e o patch
Os sistemas Unix possuem diversas ferramentas interessantíssimas para a manipulação de textos. As ferramentas apresentadas neste artigo servem para lidar com comparações e modificações em documentos.
Suponha que tenhamos o seguinte texto no arquivo exemplo.txt:
Este é um texto ilustrativo. Com ele poderemos detectar algumas das funcionalidades das ferramentas diff e patch. Podemos ter várias linhas de texto. Com ou sem acentos. Podemos, também, ter textos repetidos: as ferramentas saberão lidar com ele. Este é um texto ilustrativo. Com ele poderemos detectar algumas das funcionalidades das ferramentas diff e patch.
Imagine, agora, que façamos uma alteração qualquer e o texto se torne:
Este é um texto ilustrativo. Com ele poderemos detectar algumas das funcionalidades das ferramentas diff e patch. Podemos ter várias linhas de texto. Com ou sem acentos. Podemos também, ter textos repetidos: as ferramentas saberão lidar com ele. Este é um texto ilustrativo. Com ele poderemos detectar algumas das funcionalidades das ferramentas diff e patch.
Você sabe o que mudou? Quantas mudanças ocorreram? Quais linhas? Como eram estas linhas originalmente e como ficaram depois?
A ferramenta diff nos mostra as diferenças entre os dois textos. Antes de usá-la, entretanto, chamaremos exemplo2.txt ao texto alterado.
Este é o primeiro conceito na utilização do diff: deves ter acesso a todos os documentos que desejas comparar, em suas duas versões: antiga e nova; original e modificada.
[godoy@wintermute ~/website/src/artigos]$ diff exemplo.txt exemplo2.txt 8c8 < Podemos, também, ter textos repetidos: as ferramentas saberão lidar --- > Podemos também, ter textos repetidos: as ferramentas saberão lidar [godoy@wintermute ~/website/src/artigos]$
Esta saída nos informa que tudo o que é precedido pelo sinal "<" foi removido do texto e tudo o que é precedido pelo sinal ">" foi adicionado ao texto.
Outro conceito importante foi apresentado: o diff analisa o texto linha a linha. A menor unidade que ele pode detectar é uma linha alterada. Em nosso exemplo, houve a remoção da vírgula que antecede o 'também' e esta implicou em uma alteração na linha.
Alternativas para visualização de diferenças
Outra forma de visualização do diff pode ser obtida com a adição de chaves como -u e -c.
[godoy@wintermute ~/website/src/artigos]$ diff -c exemplo.txt exemplo2.txt *** exemplo.txt Mon Feb 17 13:27:17 2003 --- exemplo2.txt Mon Feb 17 13:31:13 2003 *************** *** 5,11 **** Podemos ter várias linhas de texto. Com ou sem acentos. ! Podemos, também, ter textos repetidos: as ferramentas saberão lidar com ele. Este é um texto ilustrativo. --- 5,11 ---- Podemos ter várias linhas de texto. Com ou sem acentos. ! Podemos também, ter textos repetidos: as ferramentas saberão lidar com ele. Este é um texto ilustrativo. [godoy@wintermute ~/website/src/artigos]$ diff -u exemplo.txt exemplo2.txt --- exemplo.txt Mon Feb 17 13:27:17 2003 +++ exemplo2.txt Mon Feb 17 13:31:13 2003 @@ -5,7 +5,7 @@ Podemos ter várias linhas de texto. Com ou sem acentos. -Podemos, também, ter textos repetidos: as ferramentas saberão lidar +Podemos também, ter textos repetidos: as ferramentas saberão lidar com ele. Este é um texto ilustrativo. [godoy@wintermute ~/website/src/artigos]$
Na opinião do autor, o uso da opção -u é o que torna a saída mais legível, permitindo uma fácil identificação do que foi alterado no texto. Obviamente a quantidade de texto mudado e as alterações feitas — aliadas à prática do usuário — definem outros fatores na identificação das mudanças.
Uso do patch
Imagine, agora, que há 500 cópias deste arquivo e todas elas devem ser alteradas para refletir o novo documento. Como fazer esta alteração de maneira automática?
Para esta tarefa, o utilitário patch vem bem a calhar. Ele é capaz de pegar a saída do diff e replicá-la em outros arquivos.
Criamos, então, um arquivo com a saída do diff. Uma convenção que pode ajudá-lo é chamar o novo arquivo com o nome final e chamar o arquivo anterior de '.OLD':
[godoy@wintermute ~/website/src/artigos]$ mv exemplo.txt exemplo.txt.OLD [godoy@wintermute ~/website/src/artigos]$ mv exemplo2.txt exemplo.txt [godoy@wintermute ~/website/src/artigos]$ diff -u exemplo.txt.OLD exemplo.txt > mudancas.patch [godoy@wintermute ~/website/src/artigos]$ cat mudancas.patch --- exemplo.txt.OLD Mon Feb 17 13:27:17 2003 +++ exemplo.txt Mon Feb 17 13:31:13 2003 @@ -5,7 +5,7 @@ Podemos ter várias linhas de texto. Com ou sem acentos. -Podemos, também, ter textos repetidos: as ferramentas saberão lidar +Podemos também, ter textos repetidos: as ferramentas saberão lidar com ele. Este é um texto ilustrativo. [godoy@wintermute ~/website/src/artigos]$
Para aplicar as mudanças basta ter o arquivo exemplo.txt original (o que agora possui a extensão .OLD) e executar o seguinte procedimento:
[godoy@wintermute ~/website/src/artigos]$ mv exemplo.txt.OLD exemplo.txt overwrite exemplo.txt? (y/n [n]) y [godoy@wintermute ~/website/src/artigos]$ patch < mudancas.patch Hmm... Looks like a unified diff to me... The text leading up to this was: -------------------------- |--- exemplo.txt.OLD Mon Feb 17 13:27:17 2003 |+++ exemplo.txt Mon Feb 17 13:31:13 2003 -------------------------- Patching file exemplo.txt using Plan A... Hunk #1 succeeded at 5. done [godoy@wintermute ~/website/src/artigos]$ cat exemplo.txt Este é um texto ilustrativo. Com ele poderemos detectar algumas das funcionalidades das ferramentas diff e patch. Podemos ter várias linhas de texto. Com ou sem acentos. Podemos também, ter textos repetidos: as ferramentas saberão lidar com ele. Este é um texto ilustrativo. Com ele poderemos detectar algumas das funcionalidades das ferramentas diff e patch. [godoy@wintermute ~/website/src/artigos]$
Revertendo patches
Um pequeno truque nos permite recuperar o arquivo original, caso o desejemos: a reversão do patch.
[godoy@wintermute ~/website/src/artigos]$ patch --reverse < mudancas.patch Hmm... Looks like a unified diff to me... The text leading up to this was: -------------------------- |--- exemplo.txt Mon Feb 17 13:27:17 2003 |+++ exemplo.txt Mon Feb 17 13:31:13 2003 -------------------------- Patching file exemplo.txt using Plan A... Hunk #1 succeeded at 5. done [godoy@wintermute ~/website/src/artigos]$ cat exemplo.txt Este é um texto ilustrativo. Com ele poderemos detectar algumas das funcionalidades das ferramentas diff e patch. Podemos ter várias linhas de texto. Com ou sem acentos. Podemos, também, ter textos repetidos: as ferramentas saberão lidar com ele. Este é um texto ilustrativo. Com ele poderemos detectar algumas das funcionalidades das ferramentas diff e patch. [godoy@wintermute ~/website/src/artigos]$
Lá está a vírgula novamente presente no texto.
Aplicações práticas e exemplos reais de uso
Mudanças simples ou curtas, como as utilizadas nos exemplos, não têm uma utilidade muito prática. Servem apenas como meros exemplos para um documento como este.
Entretanto, mudanças complexas, em vários arquivos e diretórios, podem trazer uma grande economia na transferência destas mudanças. Imagine-se trabalhando em um programa muito complexo, com uma equipe de desenvolvedores.
Você faz uma alteração no nome de uma função. Todos os desenvolvedores deverão realizar a mesma alteração nos códigos em que estão trabalhando, de modo que possa-se garantir o funcionamento do programa.
Você pode criar um diretório com uma cópia do código original e uma cópia com as alterações. Executando o diff nestas duas árvores, poderá gerar um único arquivo com as descrições das mudanças. Basta que você dê aos outros desenvolvedores este arquivo para que eles tenham seus códigos refletindo as mesmas mudanças.
Sem a utilização desta ferramenta, você teria que realizar — de maneira manual ou automatizada — a mudança em todos os arquivos, em todas as máquinas.
Uma alternativa muito mais onerosa em termos de recursos de armazenagem e largura de banda utilizada seria transferir a árvore já modificada. Entretanto, isto traria ainda outro problema: os desenvolvedores perderiam suas alterações ou teriam que comparar por si mesmos quais as mudanças sofridas no código.
Uma ferramenta que usa estes utilitários — de uma maneira um pouco diferente e mais complexa — é o CVS. No artigo Linux & CVS explico um pouco mais a respeito desta ferramenta e de como instalá-la no Linux. O procedimento para instalar o CVS no FreeBSD é o mesmo, resguardando-se, obviamente, as mudanças necessárias nos nomes de diretórios.
É muito comum na comunidade de software livre distribuir-se patches com correções e atualizações de versões de programas. Com este artigo, esperamos, você será capaz de entender o que acontece e será capaz de utilizar estes arquivos para aumentar tua produtividade.
Maiores informações
Caso precises, as páginas de manual dos utilitários diff e patch fornecem várias opções adicionais que permitirão obter estas informações de uma maneira que seja mais interessante para tuas necessidades.
Sobre este documento
Autor: Jorge Godoy
Data: 17 de fevereiro de 2003
Última atualização: 17 de fevereiro de 2003