Como criar e sincronizar automaticamente um diretório “mesclado” de vários outros diretórios sem duplicar arquivos?

3

Se eu tiver alguns diretórios de origem, por exemplo, dir1 , dir2 ... dir5 , como criar um diretório de destino "mesclado" de sincronização automática que tenha todos os arquivos e diretórios dos diretórios de origem, mas não envolva a duplicação de arquivos?

Por exemplo, tenho a seguinte estrutura de diretórios de origem ...

dir1/
  - a
  - b

dir2/
  - b   <-- Note the duplicate name, this one is more recent than dir1\b
  - c
  - dir2.1/   <-- Subdirectories present too.
      - z

dir3/
  - d

... que quando "mesclado" ficaria assim:

merge/
 - dir2.1/
     - z
 - a
 - b   <-- Which one to show is based on modified time; most recent first.
 - c
 - d

(Suponha que possa haver dezenas de diretórios com milhares de arquivos e subdiretórios.)

Todos os arquivos e diretórios na lista de origem devem permanecer no local e inalterados e o diretório de destino "mesclado" não deve ocupar nenhum armazenamento adicional; Ou seja, é possível que todos os links simbólicos sejam gerenciados por algum daemon usando inotify. Os diretórios de origem também têm arquivos e subdiretórios adicionados e removidos com freqüência, e isso precisa ser refletido, o mais rápido possível, no diretório "mesclado" também.

Alguns exemplos de uso:

Eu crio um novo arquivo, dir3/e , e ele automaticamente e imediatamente (ou em poucos segundos) aparece no diretório merge .

Eu removo o arquivo dir1/a e ele automaticamente e imediatamente (ou em poucos segundos) desaparece do diretório merge .

Edito dir3/d abrindo merge/d

Eu chamo touch on dir1/b , então ele tem uma data de modificação mais nova que dir2/b e, portanto, merge/b atualiza automaticamente para apontar para dir1/b , pois é o mais recente.

Eu removi dir1/b e agora merge/b apontará para o arquivo mais antigo dir2/b .

Eu tento criar um arquivo em merge , mas recebo um erro porque isso não faz sentido!

    
por x-x 20.03.2016 / 01:06

3 respostas

3

Combinar dinamicamente o conteúdo de vários diretórios é exatamente o que é um conjunto de união (ou sistema de arquivos da união). Existem várias implementações no Linux, mas as mais comuns resolvem a duplicação entre as ramificações sempre preferindo uma ramificação específica (por exemplo, dir2/file sempre tem precedência sobre dir1/file se ambas existirem). No entanto, acabei de descobrir mergerfs que tem políticas mais flexíveis e, em particular, permite escolher o arquivo mais recente em uma base arquivo por arquivo.

A configuração:

mkdir dir1 dir2 merge
echo 1 >dir1/b; echo 2 >dir2/a
sleep 1
echo 1 >dir1/a; echo 2 >dir2/b; echo 2 >dir2/c

Agora nós montamos. Definimos a política newest para acesso a arquivos ( search ) e modificação de metadados ( action ) e proíbem a criação ( create ) (você pode fazer a criação passar para uma das ramificações, seja sempre a mesma, ou com base no espaço disponível em disco, ou mesmo aleatoriamente!).

$ mergerfs -o category.action=newest,category.search=newest,category.create=erofs dir1:dir2:dir3 merge
$ head merge/?
==> merge/a <==
1

==> merge/b <==
2

==> merge/c <==
2

$ rm dir2/c
$ echo merge/?
a b

Para desmontar: fusermount -u merge

    
por 20.03.2016 / 20:20
0

Este é meu hack usando o bash. A desvantagem da solução é que durante a execução do script, ela cria links simbólicos para cada cópia, mas como o último nome de arquivo (com o mesmo nome) é aquele com o timestamp mais recente, o link simbólico para ele permanecerá.

Certifique-se de alterar as variáveis MDIR (dir de mesclagem) e BDIR (diretório / diretórios iniciais) antes de executá-lo.

MDIR=/tmp
(
BDIR="/tmp/ssh /etc/ssh"
for entry in $(find $BDIR -type f -exec stat --printf "%n,%Y\n" {} \;);do

  fname=$(echo $entry | cut -f 1 -d ,)
  tstamp=$(echo $entry | cut -f 2 -d ,)
  bname=$(basename $fname)

  echo $bname,$fname,$tstamp

done
) | sort -t, -nk 3 | \
while read entry;do
  bname=$(echo $entry | cut -f 1 -d ,)
  fname=$(echo $entry | cut -f 2 -d ,)
  tstamp=$(echo $entry | cut -f 3 -d ,)
  ln -svf $fname $MDIR/$bname
done
    
por 20.03.2016 / 02:18
0

Use ln para criar links simbólicos ( -s ) que permitem que vários ponteiros para o mesmo arquivo real respondam à sua pergunta principal. Seu exemplo de uso de adição automática, no entanto, agora é atendido por isso (mas isso pode ser útil para outras pessoas que leem seu título e cabeçalho).

ln -s src/of/actual/file merge_directory/pointer_link
    
por 20.03.2016 / 02:48