Como sobrescrever arquivos de destino com mv?

129

Eu tenho uma tonelada de arquivos e dirs em um subdiretório que eu quero mover para o diretório pai. Já existem alguns arquivos e dirs no diretório de destino que precisam ser sobrescritos. Arquivos que estão presentes apenas no destino devem ser deixados intactos. Posso forçar o mv a fazer isso? Ele ( mv * .. ) reclama

mv: cannot move 'xyz' to '../xyz': Directory not empty

O que estou perdendo?

    
por EricSchaefer 22.03.2011 / 17:37

7 respostas

95

Você terá que copiá-los para o destino e depois excluir a fonte, usando os comandos cp -r * .. seguido por rm -rf * .

Eu não acho que você pode "mesclar" diretórios usando mv .

    
por 22.03.2011 / 18:01
59

rsync provavelmente seria a melhor opção aqui. É tão simples quanto rsync -a subdir/ ./ .

Minha árvore de teste em filename : contents format:

./file1:root
./file2:root
./dir/file3:dir
./dir/file4:dir
./subdir/dir/file3:subdir
./subdir/file1:subdir

Executando rsync :

$ rsync -a -v subdir/ ./
sending incremental file list
./
file1
dir/
dir/file3

Dá:

./file1:subdir
./file2:root
./dir/file3:subdir
./dir/file4:dir
./subdir/dir/file3:subdir
./subdir/file1:subdir

E, em seguida, para emular mv , você provavelmente deseja remover o diretório de origem:

$ rm -r subdir/

Dando:

./file1:subdir
./file2:parent
./dir/file3:subdir
./dir/file4:dir

Se isso estiver errado, você pode fornecer um exemplo semelhante (por exemplo, usando minha árvore de teste de perto do topo desta resposta) com o resultado desejado?

    
por 22.03.2011 / 23:35
41

rsync pode excluir a fonte após as cópias com o parâmetro --remove-source-files . Esta deve ser uma maneira conveniente de fazer o que você gostaria.

Do rsync man page :

        --remove-source-files   sender removes synchronized files (non-dir)
    
por 31.01.2013 / 17:41
16

Você pode fazer isso com cp e rm , mas sem copiar a enorme quantidade de dados que você está (presumivelmente) tentando evitar a transferência. @mattdm fez alusão a isso em seu comentário e uma resposta para outra pergunta tem uma discussão mais completa sobre várias opções.

cp -rlf source destination
rm -r source

Essencialmente, a opção -l do comando cp cria links físicos para arquivos em vez de copiar seus dados para novos arquivos.

    
por 31.01.2015 / 08:34
8

Aqui está um script que move os arquivos de /path/to/source/root para o caminho correspondente em /path/to/destination/root .

  • Se houver um diretório na origem e no destino, o conteúdo será movido e mesclado recursivamente.
  • Se um arquivo ou diretório existir na origem, mas não no destino, ele será movido.
  • Qualquer arquivo ou diretório que já exista no destino é deixado para trás. (Em particular, os diretórios mesclados são deixados para trás na origem. Isso não é fácil de corrigir).

Cuidado, código não testado.

export dest='/path/to/destination/root'
cd /path/to/source/root
find . -type d \( -exec sh -c '[ -d "$dest/$0" ]' \; -o \
                  -exec sh -c 'mv "$0" "$dest/$0"' {} \; -prune \) \
    -o -exec sh -c '
        if ! [ -e "$dest/$0" ]; then
          mv -f "$0" "$dest/$0"
        fi
' {} \;
    
por 22.03.2011 / 22:55
2

Este segmento está lá fora há anos e ainda ocupa o primeiro lugar no google, então eu queria adicionar outro método. Como eu costumo fazer isso: empacotando o conteúdo do subdiretório em um tarball, movendo o tarball para o diretório pai e então extraí-lo com o comportamento padrão --overwrite. Isso faz exatamente o que você está procurando. Depois você pode remover seu subdiretório.

cd xyz
tar -cvzpf tmp.tar.gz *
mv tmp.tar.gz ../tmp.tar.gz
cd ..
tar -xvzpf tmp.tar.gz
rm -rf xyz
rm -f tmp.tar.gz
    
por 13.04.2016 / 10:52
0

Se você tiver armazenamento suficiente, poderá fazê-lo da seguinte maneira:

mv -bfv directory_1/* directory_2/ # all duplicate source files/directories 
                                   # will have ~ appended to them
find -name "*~" -delete            # will recursively find and delete all files 
                                   # with ~ on the end

Verifique se não há arquivos importantes com um ~ no final, mas se houver, você pode adicionar --suffix=whateveryouwant em vez do padrão.

    
por 15.03.2016 / 08:01