Teste o GNU diff
versão 3.3 ou posterior com a opção --no-dereference
(e presumivelmente a opção --recursive):
diff --recursive --no-dereference tree1root tree2root
No Linux, pode-se usar o comando diff
para verificar diferenças de arquivos. Eu o uso para verificar as diferenças entre dois módulos, ambos copiados para /tmp
.
No entanto, ambos os módulos possuem links simbólicos, que podem não estar apontando para o arquivo correto, já que os módulos foram copiados para o diretório /tmp
. Mas isso não importa. O que eu quero verificar é se os links simbólicos são os mesmos.
Por exemplo, em um módulo, o link simbólico lê
/home/test/file1
e no outro o link simbólico diz:
/etc/rc.d/whatever
diff
agora gera um erro porque - em geral - não consegue encontrar o arquivo. Mas eu quero deixar diff
dizer: "Ei, esses links simbólicos não são os mesmos", independentemente de os links apontarem para arquivos válidos ou não.
Pergunta: Como é possível para diff
fazer isso, ou seja, não tentando seguir links, mas para diferenciar os próprios links?
Teste o GNU diff
versão 3.3 ou posterior com a opção --no-dereference
(e presumivelmente a opção --recursive):
diff --recursive --no-dereference tree1root tree2root
Desde a versão 3.3, o GNU diff suporta não desreferenciar links simbólicos, mas compara os caminhos para os quais eles apontam.
Instale o GNU diffutils > = 3.3 e use a opção '--no-dereference'; não há uma opção curta para isso.
O diagnóstico será silencioso se os caminhos forem iguais ou:
Symbolic links /tmp/noderef/a/symlink and /tmp/noderef/b/symlink differ
se os caminhos forem diferentes.
Com ferramentas GNU:
diff <(cd dir1 && find . -type l -printf '%p -> %l\n'|sort) \
<(cd dir2 && find . -type l -printf '%p -> %l\n'|sort)
Estritamente falando, não é possível diferenciar entre um link simbólico chamado a
que aponta para b -> c
e um chamado a -> b
que aponta para c
, sem mencionar os problemas com nomes de arquivos contendo caracteres de nova linha, mas contribui para uma saída mais legível do que a mais robusta:
diff <(cd dir1 && find . -type l -printf '%p // %ldiff <(cd dir1 && find . -type l -printf '%p -> %l\n'|sort) \
<(cd dir2 && find . -type l -printf '%p -> %l\n'|sort)
'|tr '\ndiff <(cd dir1 && find . -type l -printf '%p // %l%pre%'|tr '\n%pre%' '%pre%\n'|sort) \
<(cd dir2 && find . -type l -printf '%p // %l%pre%'|tr '\n%pre%' '%pre%\n'|sort)
' '%pre%\n'|sort) \
<(cd dir2 && find . -type l -printf '%p // %l%pre%'|tr '\n%pre%' '%pre%\n'|sort)
Lá, usamos //
como o separador (que não pode ocorrer na saída de find
para %p
) e convertemos os caracteres de nova linha em caracteres NUL (o que não pode ocorrer na expansão de %p
nem %l
).
Se eu entendi corretamente, você quer verificar se os links simbólicos apontam para o mesmo destino teórico, ou se um não é um link simbólico, o outro arquivo se vincula ao mesmo arquivo. Isso deve fazer o que você quer:
#!/bin/bash
if [[ "$(readlink -m -- "$1")" == "$(readlink -m -- "$2")" ]]; then
echo "files match"
else
echo "files don't match"
exit 1
fi
$ > foo
$ ln -s foo bar
$ ln -s foo baz
$ ./script bar baz
files match
$ ./script bar foo
files match
$ ln -sf qux bar
$ ./script bar foo
files don't match