Qual é a melhor maneira de mesclar dois diretórios no mesmo sistema de arquivos no linux?

1

Eu tenho dois diretórios que precisam ser mesclados. Os arquivos nesses dois diretórios são todos arquivos grandes (> = 500MB).

O que eu quero arquivar: Para arquivos no diretório de origem: se ele não existir no diretório de destino, mv para o diretório de destino (que é rápido, pois estamos basicamente criando um novo link físico e desvinculando a origem Arquivo); se existir no diretório de destino, copie o arquivo de origem e remova o arquivo de origem.

A maneira mais comum de mesclar diretórios no sistema Linux é usar a opção rsync with --remove-source-files . Mas isso é lento porque ele faz a operação de cópia, mesmo que o arquivo de destino não exista.

Alguma ideia melhor? Obrigado.

    
por yegle 12.01.2014 / 21:42

3 respostas

3

Basicamente, o que você descreveu é mover um destino de sobregravação de arquivos, se existir. Então, apenas mova-os.

    
por 12.01.2014 / 21:47
2

mv opções são todas sobre resolução de conflitos:

Escolha um:

-f  force (always overwrite)
-i  interactive (ask whether to overwrite)
-n  no clobber (no overwrite)

E isso também é bom:

-v  verbose

Caso contrário, os dados podem se perder e / ou não ficará claro o que aconteceu exatamente.

mv também é superior no mesmo fs porque está apenas atualizando inodes de diretório, os arquivos não devem ser mexidos. A outra coisa é que quanto maior a operação, maior a chance de as coisas darem errado, como soft-errors.

    
por 13.01.2014 / 02:42
0

Há um caso em que mv falha. Veja alguns dados de exemplo:

mkdir -p src/d dest/d
touch src/d/f1 dest/d/f2

Veja como mv falha:

$ mv src/* dest/
mv: cannot move 'src/d' to 'dest/d': Directory not empty
$ mv -f src/* dest/
mv: cannot move 'src/d' to 'dest/d': Directory not empty
$ mv -fv src/* dest/
mv: cannot move 'src/d' to 'dest/d': Directory not empty
$ mv -fvi src/* dest/
mv: overwrite 'dest/d'? y
mv: cannot move 'src/d' to 'dest/d': Directory not empty
$ mv -fvi -t dest/ src/*      
mv: overwrite 'dest/d'? y
mv: cannot move 'src/d' to 'dest/d': Directory not empty

Portanto, crie um arquivo de script:

vim supermove

Este exemplo não faz verificação de erros (ISENÇÃO DE RESPONSABILIDADE: funciona para mim, mas por favor teste que funciona para você ... talvez com echo antes de mv ), e sobrescreverá arquivos com o mesmo caminho. E ele usa find com \; , que é terrivelmente ineficiente, mas + não funciona corretamente com "$dest" prefixado. Versões mais antigas farão alguns dirs sem o caminho prefixado, e versões mais novas do find dirão:

find: In '-exec ... {} +' the '{}' must appear by itself, but you specified 'dest/{}'

Você provavelmente poderia encontrar uma maneira de corrigir isso com xargs embora. (Demorou alguns minutos nos arquivos 64k 8TB que eu estava movendo). Adicione este conteúdo:

#!/bin/bash

src=$1
dest=$2

src=$(readlink -f "$src")
dest=$(readlink -f "$dest")

cd "$src"

# also copy hidden files
shopt -s dotglob

# make dirs (missing old permission,acl,xattr data), and then mv the files
time find * -type d -exec mkdir -p "$dest"/{} \;
time find * -type f -exec mv {} "$dest"/{} \;

# also copy permissions, acls, xattrs
rsync -aAX "$src"/ "$dest"/

E torne-o executável:

chmod +rx supermove

E execute-o

./supermove src/ dest/

E o resultado ... antes:

$ find src dest
src/
src/d
src/d/f1
dest/
dest/d
dest/d/f2

Depois:

$ find src dest
src
src/d
dest
dest/d
dest/d/f1
dest/d/f2

Agora, src/ deve ser apenas dirs vazios. Se assim for, você pode rm -r src para limpar.

    
por 10.11.2017 / 11:25

Tags