terça-feira, 21 de dezembro de 2010

Buscar diferenças entre diretórios



Eis um problema que já tive que enfrentar diversas vezes: alterar um parâmetro de configuração que não sabia onde estava! Ou ainda: investigar o que foi alterado em algo que antes funcionava e passou a dar problema.

Como na informática tudo gira em torno de 0s e 1s, se algo mudou, tem que haver diferença entre arquivos e ou diretórios. Digamos que você possua dois diretórios contendo parâmetros de configuração de determinado software. Um deles funciona, o outro não. Como saber o que há de diferente entre eles?

Richard Stallman, junto com outros colaboradores da GNU nos proveu o utilitário diff no Linux (ou melhor, GNU/Linux), o qual permite a comparação entre dois arquivos de texto ou binários. O problema é que esse comando precisa ser invocado para cada par de arquivos, o que pode se tornar um complexo "trabalho de estagiário" dependendo da quantidade de subdiretórios e arquivos considerados.

Para atacar essa questão, criei o script em Shell diffdirs.sh contendo o código a seguir:

#!/bin/bash

if [ $# -ne 2 ]
then
    echo "Uso: $0 <dir1> <dir2>"
    exit 1
fi

dir1="$1"
dir2="$2"
list="/tmp/$$.list"
cont="/tmp/$$.cont"

cd $dir1
find -type f | sed 's/^\.\///' > $list
cd - > /dev/null

echo "Analisando diferenças entre diretórios:"
echo "- $dir1"
echo "- $dir2"

while read arq
do
    if ! diff $dir1/$arq $dir2/$arq > $cont
    then
        echo -e "\n$arq:"
        cat $cont
    fi
done < $list

rm -f $list $cont

exit 0


No caso em questão, precisava saber em qual diretório e arquivo residia uma configuração específica da IDE Eclipse. Como não dispunha de ambiente gráfico, a opção foi fazer tudo em modo texto. E esse script resolveu o problema! Veja o resultado exibido após a sua execução:

$ ./diffdirs.sh 
Uso: ./diffdirs.sh <dir1> <dir2>

$ ./diffdirs.sh ws35a/ ws35b/


Analisando diferenças entre diretórios:
- ws35a
- ws35b

.metadata/.plugins/org.eclipse.jdt.core/nonChainingJarsCache:
Os arquivos binários ws35a/.metadata/.plugins/org.eclipse.jdt.core/nonChainingJarsCache e ws35b/.metadata/.plugins/org.eclipse.jdt.core/nonChainingJarsCache são diferentes

.metadata/.plugins/org.eclipse.core.runtime/.settings/org.maven.ide.eclipse.prefs:
1c1
< #Tue Dec 21 09:47:38 AMT 2010
---
> #Tue Dec 21 09:48:27 AMT 2010
3d2
< eclipse.m2.downloadSources=true
10d8
< eclipse.m2.downloadJavadoc=true


Agora é só copiar o script para um diretório no PATH do usuário. :D