Basicamente, o que você descreveu é mover um destino de sobregravação de arquivos, se existir. Então, apenas mova-os.
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.
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.
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.
Tags linux