Quebrar todos os hardlinks dentro de uma pasta

8

Eu tenho uma pasta que contém um certo número de arquivos que possuem links físicos (na mesma pasta ou em outro lugar), e eu quero desvincular esses arquivos, para que eles se tornem independentes e as alterações no conteúdo deles venham t afetará qualquer outro arquivo (sua contagem de links se torna 1).

Abaixo, eu dou uma solução que basicamente copia cada hard link para outro local, então o move de volta no lugar.

No entanto, este método parece bastante simples e propenso a erros, por isso gostaria de saber se existe algum comando que irá desvincular um ficheiro para mim.

Resposta bruta:

Encontre arquivos que possuam links físicos ( Editar : para encontrar também sockets, etc. que possuam hardlinks, use find -not -type d -links +1 ):

find -type f -links +1

Um método bruto para desvincular um arquivo (copiá-lo para outro local e movê-lo de volta): Edit: Como Celada disse, é melhor fazer um cp -p abaixo, para evitar perder timestamps e permissões. Editar: Crie um diretório temporário e copie para um arquivo sob ele, em vez de sobrescrever um arquivo temporário, ele minimiza o risco de sobrescrever alguns dados, embora o comando mv ainda seja arriscado (obrigado @Tobu).

# This is unhardlink.sh
set -e
for i in "$@"; do
  temp="$(mktemp -d ./hardlnk-XXXXXXXX)"
  [ -e "$temp" ] && cp -ip "$i" "$temp/tempcopy" && mv "$temp/tempcopy" "$i" && rmdir "$temp"
done

Portanto, para desvincular todos os links físicos ( Editar : alterou -type f para -not -type d , consulte acima):

find -not -type d -links +1 -print0 | xargs -0 unhardlink.sh
    
por Georges Dupéron 06.05.2012 / 19:39

2 respostas

6

Há espaço para aprimoramentos em seu script, por exemplo, adicionando uma opção -p ao comando cp para que as permissões e registros de data e hora sejam preservados na operação de não-vínculo e você possa adicionar alguns erros para que o temp O arquivo é excluído em caso de erro, mas a idéia básica de sua solução é a única que funcionará. Para desvincular um arquivo, você deve copiá-lo e, em seguida, mover a cópia de volta sobre o nome original. Não existe uma solução "menos bruta", e esta solução tem condições de corrida, caso outro processo esteja acessando o arquivo ao mesmo tempo.

    
por 06.05.2012 / 20:26
3

Se você quiser gravar espaço em disco e tiver uma versão relativamente moderna de tar (por exemplo, o que está no Ubuntu 10.04 e no CentOS 6), é possível jogar com a opção --hard-dereference .

Algo como:

$ cd /path/to/directory
$ ls -l *
bar:
total 12
-rw-rw-r-- 2 cjc cjc 2 May  6 19:07 1
-rw-rw-r-- 2 cjc cjc 2 May  6 19:07 2
-rw-rw-r-- 1 cjc cjc 2 May  6 19:07 3

foo:
total 12
-rw-rw-r-- 2 cjc cjc 3 May  6 19:07 1
-rw-rw-r-- 2 cjc cjc 2 May  6 19:07 2
-rw-rw-r-- 1 cjc cjc 2 May  6 19:07 4

(onde eu corri ln foo/[12] bar )

$ tar cvf /tmp/dereferencing.tar --hard-dereference .
$ tar xvf /tmp/dereferencing.tar
$ ls -l *
bar:
total 12
-rw-rw-r-- 1 cjc cjc 2 May  6 19:07 1
-rw-rw-r-- 1 cjc cjc 2 May  6 19:07 2
-rw-rw-r-- 1 cjc cjc 2 May  6 19:07 3

foo:
total 12
-rw-rw-r-- 1 cjc cjc 3 May  6 19:07 1
-rw-rw-r-- 1 cjc cjc 2 May  6 19:07 2
-rw-rw-r-- 1 cjc cjc 2 May  6 19:07 4

Da página do manual:

   --hard-dereference
          follow hard links; archive and dump the files they refer to
    
por 07.05.2012 / 01:11

Tags