Utilitário de movimento recursivo no Unix?

6

Às vezes, tenho duas árvores que costumavam ter o mesmo conteúdo, mas cresceram fora de sincronia (porque eu movi discos ao redor ou qualquer outra coisa). Um bom exemplo é uma árvore onde eu espelhei pacotes upstream do Fedora.

Eu quero mesclar essas duas árvores novamente movendo todos os arquivos de tree1 para tree2.

Geralmente faço isso com:

rsync -arv tree1/* tree2

Em seguida, exclua tree1.

No entanto, isso leva muito tempo e espaço em disco, e seria muito mais fácil de ser feito:

mv -r tree1/* tree2

Em outras palavras, um movimento recursivo. Seria mais rápido porque, antes de mais nada, nem mesmo copiaria, apenas moveria os inodes e, segundo, eu não precisaria de uma exclusão no final.

Isso existe?

Como um caso de teste, considere a seguinte sequência de comandos:

$ mkdir -p a/b
$ touch a/b/c1
$ rsync -arv a/ a2
sending incremental file list
created directory
./
b/
b/c1
b/c2

sent 173 bytes  received 57 bytes  460.00 bytes/sec
total size is 0  speedup is 0.00
$ touch a/b/c2

Qual comando teria agora o efeito de mover a / b / c2 para a2 / b / c2 e, em seguida, excluir a subárvore a (já que tudo nela já está na árvore de destino)?

    
por Thomas Vander Stichele 11.06.2009 / 15:24

10 respostas

2

Por mp (1) manpage do mv do gnu:

-u, --update move only when the SOURCE file is newer than the destination file or when the destination file is missing

    
por 11.06.2009 / 15:43
2

o mv -uf dir1/* dir2/ proposto move os diretórios (sub), não cada arquivo. você pode tentar usar find

cd dir1
find . -type d -exec mkdir -p dir2/"{}" \;
find . -type f -exec mv -uf "{}" dir2/"{}" \;

ou algo semelhante

    
por 11.06.2009 / 20:02
1

Não

mv -uf tree1/* tree2/

trabalho?

    
por 11.06.2009 / 15:44
1

Midnight Commander (mc) também é bom para esse tipo de coisa. Marque os arquivos com CTRL-t, pressione F6 e, quando solicitar a substituição dos arquivos de destino, escolha Atualizar, se desejar substituir arquivos antigos.

    
por 11.06.2009 / 15:52
1

Você pode usar "cp -l & rm" para mover no dispositivo:

cp -alv --backup=numbered tree1/* tree2 &&
rm -rf tree1/
  • -l de cp para usar links físicos em vez de copiar (isso também evita operações entre dispositivos)
  • --backup=numbered de cp para fazer backup dos arquivos existentes no diretório de destino

E tenha cuidado com essas duas questões:

  • use && para impedir que seus dados não copiados sejam removidos, se você os executar acidentalmente em destinos de dispositivos diferentes. (no caso do corss-device cp sai com um status de " 1 ", pelo menos para o GNU coreutils)
  • arquivos começando com " . " em tree1 , você os perderá se houver algum.
por 31.08.2012 / 04:11
1

A resposta de Javier com o find funciona bem, exceto pelo fato de não remover os diretórios originais. Adicione no final:

rmdir $(find . -type d  |grep -v ^\.$)
    
por 28.06.2013 / 19:09
0

err

mv dir1/* dir2/

ou simplesmente

rsync -arv --remove-source-files  tree1/* tree2

deve ser o suficiente, você provavelmente terá problemas em algum momento, quando muitas entradas estiverem em dir1 .

find sourcedir -maxdepth 1 -exec echo mv {} targetdir/ \;

deve ser uma boa opção

find sourcedir -maxdepth 1 -print0 |xargs -0 -I _ echo mv _ targetdir
find sourcedir -maxdepth1 -exec mv {} targetdir/ +

não são realmente necessários, porque o mv usa apenas 2 opções (destino de origem), então você terá que conviver com a multiplicidade de processos nesse caso.

    
por 11.06.2009 / 15:44
0
cd /tree1
mv * /tree2 

Isso não moverá arquivos ou pastas ocultos, mas o seu exemplo original também não.

    
por 12.06.2009 / 14:00
0

Eu acho que mv não faz o que você acha que faz.

Um sistema de arquivos unix possui 3 componentes:

  • entradas de diretório
  • inodes
  • blocos

Uma entrada de diretório aponta para um inode.

O inode tem os metadados sobre o arquivo (é um arquivo, um diretório, um pipe nomeado? Quem é o proprietário? Quais são as permissões? Que blocos esse inode usa?

Os blocos são as coisas que realmente contêm o conteúdo do arquivo.

Então - quando você "mv" um arquivo, tudo o que você realmente está fazendo é desvincular a primeira entrada do diretório e vinculá-la em outro lugar.

snoopy -> inode 333 
woodstock -> inode 333

Nenhum dado é duplicado / copiado. Você cria o link snoopy, depois cria o link woodstock e, em seguida, exclui o link snoopy. (as coisas são um pouco diferentes com os diretórios, porque normalmente você não pode criar diretórios com hardlink, mas mesmo assim o nome "link" apenas muda).

E se você estiver mudando de um sistema de arquivos para outro? Antigamente, o mv lançava um erro e tornava explícito que você não podia mover um arquivo de um sistema de arquivos para outro. Hoje em dia, parece que o mv silenciosamente copia os dados e depois apaga o original.

Antigamente, como não era possível mover dados de um sistema de arquivos para outro, você adquiriu o hábito de usar expressões idiomáticas como

tar -cf -. | (cd / novo / local & & tar -xf -)

depois, você exclui os dados antigos. Parte do motivo para usar o tar era que, antigamente, o cp destruiria metadados como "este é um link simbólico" e "é um link difícil" e, em vez disso, você só obteria novas cópias desse arquivo como arquivos comuns. Mesmo assim, você precisa dar sinalizadores "cp" para dizer para preservar esse tipo de estrutura.

Não há como evitar a "movimentação" de muitos dados se for de um sistema de arquivos para outro. Não importa se você está usando novo movimento ou rsync ou tar ou cpio.

Mas, se você mantiver todos os dados no mesmo sistema de arquivos, isto:

mv / filesystem-1 / grande / diretório * / filesystem-1 / big2 /

que será extremamente rápido porque está apenas alterando as entradas do diretório e não movendo realmente nenhum dado real.

Há outros problemas em jogo, como o que você deve fazer se já houver um arquivo / diretório no novo local, bem como o local de origem?

    
por 28.06.2013 / 19:39
-1

mude para o diretório que você deseja mover e fazer

tar cf - * | ( cd /target; tar xfp -)

Mais rápido que mv ...

    
por 11.06.2009 / 16:11