Usando, rdfind
encontrei muitos arquivos com links físicos (~ 60-90) e quero desvincular todos eles. Uma solução possível é apenas encontrar todos os arquivos -link +1
e copiá-los, excluí-los e movê-los de volta para o nome do link.
Existe uma solução melhor? Existe uma maneira mais fácil de fazer isso?
Responder1
Você pode fazer:
find . -type f -links +1 -exec sh -c '
{ rm -f "$1" && cat > "$1"; } < "$1"' sh {} \;
mas isso não preservará os metadados do arquivo. No Linux, você pode fazer:
find . -type f -links +1 -exec sh -c '
{ rm -f "$1" && cp -p /proc/self/fd/0 "$1"; } < "$1"' sh {} \;
Observe que se cat
ou cp
falhar (como no disco cheio), você perderá o conteúdo do arquivo que cat
não cp
conseguiu copiar.
Usamos -exec {} \;
em vez de -exec {} +
para que a contagem de links do arquivo seja atualizada depois que o arquivo for encontrado, para que find
nãoencontraro último link se a contagem de links cair para 1 (o que significa que para um arquivo com contagem inicial de links de 4, apenas 3 instâncias serão substituídas).
Com GNU tar
, você também pode fazer:
find . -type f -links +1 -print0 |
tar --hard-dereference --null -T - -cf - | tar xpf -
Isso executará menos comandos, mas substituirá mais arquivos.
Você pode ver alguns:
tar: ./file: file changed as we read it
para arquivos grandes, mas tudo bem, pois o segundo tar
desvinculará o arquivo antes de sobrescrevê-lo, o que será muito semelhante à primeira abordagem. É apenas o primeiro tar
que percebe a diminuição da contagem de links (e o ctime mudando como resultado) quando o segundo tar desvincula o arquivo.