Qual é a melhor maneira de desvincular arquivos com link físico?

3

Usando rdfind , encontrei muitos arquivos com link físico (~ 60-90) e desejo desvincular todos eles. Uma solução possível é encontrar todos os arquivos -link +1 e apenas 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?

    
por zanglerecke 07.06.2016 / 23:09

2 respostas

2

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 isso:

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 / cp não conseguiu copiar.

Usamos -exec {} \; em vez de -exec {} + para que a contagem de links do arquivo seja atualizada depois que o arquivo for encontrado, de forma que find não encontre o último link se o link count caiu para 1 (o que significa que para um arquivo com contagem inicial de links de 4, apenas 3 instâncias serão sobrescritas).

Com o 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 sobrescreverá mais arquivos.

Você pode ver alguns:

tar: ./file: file changed as we read it

para arquivos grandes, mas tudo bem, já que o segundo tar irá desvincular o arquivo antes de sobrescrevê-lo. Isso será muito semelhante à primeira abordagem. É apenas a primeira tar a notar que a contagem de links está diminuindo (e a mudança da hora como resultado) quando o segundo tar desassocia o arquivo.

    
por 07.06.2016 / 23:34
0

Eu acredito que copie , delete , e volte é a maneira de fazer isso.

Para um grande número de arquivos, você não quer executar três processos para cada arquivo. Você poderia usar cpio para reduzir o número de processos.

Dentro da sua árvore:

find_the_hardlinks > hardlinks #find your hardlinks
< hardlinks cpio -pdv ../the_copy
< hardlinks | rm -d '\n'  #delete the links
pwd=$PWD; cd ../the_copy; 
< "$pwd/hardlinks" cpio -pdlv "$pwd" #hardlink back from copy
cd "$pwd"; rm -rf ../the_copy #remove the copy so it's like a move

Não é exatamente fácil, mas é bastante eficiente e pode ser inserido em um script genérico.

    
por 07.06.2016 / 23:39