Mesclando pastas com mv?

122

Se eu usar mv para mover uma pasta chamada "pasta" para um diretório que já contenha "pasta", eles serão mesclados ou substituídos?

    
por Dominique 03.05.2014 / 20:41

9 respostas

93

mv não pode mesclar ou sobrescrever diretórios, ele falhará com a mensagem "mv: não pode mover 'a' para 'b': Diretório não vazio" , mesmo quando você estiver usando o --force opção.

Você pode contornar isso usando outras ferramentas (como rsync , find ou mesmo cp ), mas é necessário considerar cuidadosamente as implicações:

  • rsync pode mesclar o conteúdo de um diretório em outro (idealmente com a opção --remove-source-files 1 para excluir com segurança apenas os arquivos de origem que foram transferidos com êxito e com a permissão / propriedade / preservação de horário usual opção -a se desejar)
    mas esta é uma operação de cópia completa e pode, portanto, ser muito intensiva em disco.
  • Você pode usar find para recriar sequencialmente a estrutura de diretórios de origem no destino e, em seguida, mover individualmente os arquivos reais < br> … mas isso tem que recorrer pela origem várias vezes e pode encontrar condições de corrida (novos diretórios sendo criados na origem durante o processo de várias etapas)
  • cp pode criar links físicos (basta inserir ponteiros adicionais para o mesmo arquivo existente), o que cria um resultado muito semelhante a uma mesclagem mv (e é muito eficiente em termos de IO, pois somente os ponteiros são criados e nenhum dado real deve ser copiado)
    mas isso novamente sofre de uma possível condição de corrida (novos arquivos na origem sendo excluídos mesmo que não tenham sido copiados na etapa anterior)

Quais dessas soluções alternativas (se houver) serão apropriadas dependerão muito do seu caso de uso específico.
Como sempre, pense antes de executar qualquer um desses comandos e tenha backups.

1: Observe que rsync --remove-source-files não excluirá nenhum diretório, então você terá que fazer algo como find -type d -empty -delete depois para se livrar da árvore de diretórios de fontes vazias.

    
por 03.05.2014 / 20:47
78
rsync -av /source/ /destination/
(after checking)
rm -rf /source/
    
por 03.05.2014 / 20:58
53

Você pode usar a opção -l do comando cp , que cria links físicos de arquivos no mesmo sistema de arquivos em vez de cópias de dados completas. O comando a seguir copia a pasta source/folder para uma pasta pai ( destination ) que já contém um diretório com o nome folder .

cp -rl source/folder destination
rm -r source/folder

Você também pode usar o -P ( --no-dereference - não desrefere links simbólicos) ou -a ( --archive - preservar todos os metadados, também inclui -P opção), dependendo do seu necessidades.

    
por 09.12.2014 / 22:32
21

Eu recomendaria estas quatro etapas:

cd ${SOURCE}; 
find . -type d -exec mkdir -p ${DEST}/\{} \; 
find . -type f -exec mv \{} ${DEST}/\{} \; 
find . -type d -empty -delete

ou melhor ainda, aqui está um script que implementa semântica semelhante a mv :

#!/bin/bash

DEST="${@:${#@}}"
ABS_DEST="$(cd "$(dirname "$DEST")"; pwd)/$(basename "$DEST")"

for SRC in ${@:1:$((${#@} -1))}; do   (
    cd "$SRC";
    find . -type d -exec mkdir -p "${ABS_DEST}"/\{} \;
    find . -type f -exec mv \{} "${ABS_DEST}"/\{} \;
    find . -type d -empty -delete
) done
    
por 15.09.2014 / 07:33
15

Aqui está uma maneira de mesclar os diretórios. É muito mais rápido que o rsync, pois apenas renomeia os arquivos em vez de copiá-los e excluí-los.

cd source; find -type f -print0 | xargs -0 -n 1 -I {} mv '{}' 'dest/{}'
    
por 05.09.2014 / 06:48
4

Uma maneira de conseguir isso seria usar:

mv folder/* directory/folder/
rmdir folder

Desde que não haja dois arquivos com o mesmo nome em folder e directory/folder , você obterá o mesmo resultado, ou seja, a mesclagem.

    
por 04.05.2014 / 05:39
2

Para as cópias mais puras, eu uso o método de cópia blockread do tar (-) B.

exemplo, do caminho de origem:

tar cBf - <sourcefolder> | (cd /your/target/folder ; tar xBf -)

isso cria uma cópia exata da árvore de origem, COM o proprietário e as permissões intactas. E se a pasta de destino existir, os dados serão mesclados. Somente arquivos que já existem serão sobrescritos.

Quando a ação de cópia for bem-sucedida, você poderá remover a origem ( rm -rf <source> ). Claro que isto não é um movimento exato: os dados serão copiados, até que você remova a fonte.

Como opção, você pode ser detalhado (exibir na tela o arquivo sendo copiado), com -v: tar cBvf -

  • c : criar
  • B : ler bloco completo (para leitura de tubo)
  • v : verbose
  • f : arquivo para gravar
  • x : extrair
  • - : stdout / stdin

sourcefolder também pode ser * (para qualquer coisa na pasta atual)

    
por 26.06.2017 / 16:49
1

Aqui está um script que funcionou para mim. Eu prefiro mv over rsync, então eu uso as soluções de Jewel e Jonathan Mayer.

#!/bin/bash

# usage source1 .. sourceN dest

length=$(($#-1))
sources=${@:1:$length}
DEST=$(readlink -f ${!#})
for SRC in $sources; do
    pushd $SRC;
    find . -type d -exec mkdir -p ${DEST}/{} \;
    find . -type f -exec mv {} ${DEST}/{} \;
    find . -type d -empty -delete
    popd
done
    
por 29.11.2014 / 21:13
1

Não é uma boa ideia usar comandos como cp ou rsync. Para arquivos grandes, levará muito tempo. O mv é muito mais rápido, pois só atualiza os inodes sem copiar os arquivos fisicamente. A melhor opção é usar o gerenciador de arquivos do seu sistema operacional. Para o Opensuse, existe um gerenciador de arquivos chamado Konquerer. Ele pode mover arquivos sem copiá-los. Tem a função "cortar e colar" como no Windows. Basta selecionar todos os subdiretórios no diretório A. Clique com o botão direito e "mova-se" para o diretório B, que pode conter subdiretórios com os mesmos nomes. Ele irá fundi-los. Existem também opções para substituir ou renomear arquivos com o mesmo nome.

    
por 26.02.2016 / 14:43