Pergunta

Eu vi o seguinte uso interessante de tar em scripts Bash de um colega de trabalho:

`tar cf - * | (cd <dest> ; tar xf - )`

Aparentemente, ele funciona muito como -av rsync faz, mas mais rápido. A pergunta surge, como?

-m


Editar : alguém pode explicar por deve esta solução ser preferível sobre o seguinte?

cp -rfp * dest

O ex-mais rápido?

Foi útil?

Solução

Sobre a diferença entre CP e tar para copiar as hierarquias de diretório, um experimento simples pode ser conduzida para mostrar a diferença:

alastair box:~/hack/cptest [1134]% mkdir src
alastair box:~/hack/cptest [1135]% cd src
alastair box:~/hack/cptest/src [1136]% touch foo
alastair box:~/hack/cptest/src [1137]% ln -s foo foo-s
alastair box:~/hack/cptest/src [1138]% ln foo foo-h
alastair box:~/hack/cptest/src [1139]% ls -a
total 0
-rw-r--r--  2 alastair alastair    0 Nov 25 14:59 foo
-rw-r--r--  2 alastair alastair    0 Nov 25 14:59 foo-h
lrwxrwxrwx  1 alastair alastair    3 Nov 25 14:59 foo-s -> foo
alastair box:~/hack/cptest/src [1142]% mkdir ../cpdest
alastair box:~/hack/cptest/src [1143]% cp -rfp * ../cpdest
alastair box:~/hack/cptest/src [1144]% mkdir ../tardest
alastair box:~/hack/cptest/src [1145]% tar cf - * | (cd ../tardest ; tar xf - )
alastair box:~/hack/cptest/src [1146]% cd ..
alastair box:~/hack/cptest [1147]% ls -l cpdest
total 0
-rw-r--r--  1 alastair alastair    0 Nov 25 14:59 foo
-rw-r--r--  1 alastair alastair    0 Nov 25 14:59 foo-h
lrwxrwxrwx  1 alastair alastair    3 Nov 25 15:00 foo-s -> foo
alastair box:~/hack/cptest [1148]% ls -l tardest
total 0
-rw-r--r--  2 alastair alastair    0 Nov 25 14:59 foo
-rw-r--r--  2 alastair alastair    0 Nov 25 14:59 foo-h
lrwxrwxrwx  1 alastair alastair    3 Nov 25 15:00 foo-s -> foo

A diferença está nos arquivos com link. Observe como os arquivos com link são copiados individualmente com cp e junto com tar. Para fazer a diferença mais óbvia, ter um olhar para os inodes para cada:

alastair box:~/hack/cptest [1149]% ls -i cpdest
24690722 foo  24690723 foo-h  24690724 foo-s
alastair box:~/hack/cptest [1150]% ls -i tardest
24690801 foo  24690801 foo-h  24690802 foo-s

Há provavelmente outras razões para preferir alcatrão, mas este é um grande problema, pelo menos se você tiver arquivos extensivamente hard-vinculados.

Outras dicas

Ele escreve o arquivo para saída padrão e tubos para um subprocesso - envolto pelos parênteses - que alterações em um diretório diferente e lê / extratos de entrada padrão. Isso é o que o personagem traço após o meio argumento f. É basicamente copiar todos os arquivos visíveis e subdiretórios do diretório atual para outro diretório.

Para um diretório com 25.000 arquivos vazios:

$ time { tar -cf - * | (cd ../bar; tar -xf - ); }
real    0m4.209s
user    0m0.724s
sys 0m3.380s

$ time { cp * ../baz/; }
real    0m18.727s
user    0m0.644s
sys 0m7.127s

Para um diretório com 4 arquivos de 1073741824 bytes (1GB) cada

$ time { tar -cf - * | (cd ../bar; tar -xf - ); }
real    3m44.007s
user    0m3.390s
sys 0m25.644s

$ time { cp * ../baz/; }
real    3m11.197s
user    0m0.023s
sys 0m9.576s

Meu palpite é este fenômeno é altamente filesystem-dependente. Se eu estiver certo, você verá uma diferença drástica entre um sistema de arquivos que é especializada em vários arquivos pequenos, como o reiserfs 3,6, e um sistema de arquivos que é melhor em lidar com arquivos grandes.

(eu corri os testes acima em HFS +.)

Este é um uso exclusivo de tubos. Basicamente, o primeiro tar normalmente escreve diretamente para um arquivo, mas em vez disso, vai escrever para stdout (a -), que é então redirecionado para o outro tar que leva stdin em vez de um arquivo. Basicamente, esta é a mesma coisa que tarring para um arquivo e untarring mais tarde, exceto sem o arquivo no meio.

O livro PowerTools tem a cópia como:

tar cf - * | (cd <dest> && tar xvBf - )

O '&&' é uma condicional que verifica o código de retorno do comando anterior. IHat é, se o "cd" falhou, o "tar xf -" não seria executado. Eu sempre jogar em um -v (verbose) e uma (entrada reblock) -B.

Eu uso tar o tempo todo. É especialmente útil para copiar para um sistema remoto, tais como:

cvf tar -. | ssh alguém @ somemachine '(cd algum lugar && tar XBF -)'

tar cf - * | (cd <dest> ; tar xf - )

vai tar todas as não ocultas arquivos / diretórios do diretório atual para stdout, então tubulação que em stdin uma nova subshells. Esse shell primeiro altera o diretório de trabalho atual para <dest>, e depois untars-lo para esse diretório.

Algumas versões antigas do cp não tinha -f / p (e similares) opções para preservar as permissões, então este truque tar fez o trabalho.

Eu acredito que o tar vai fazer um estilo do Windows 'merge' operação com diretórios profundamente aninhadas, enquanto que o cp irá substituir sub-diretórios.

Por exemplo, se você tem o layout:

dir/subdir/file1

e você copiá-lo para um destino que contém:

dir/subdir/file2

Em seguida, com cópia que você vai ficar com:

dir/subdir/file1

Mas com o comando tar, o seu destino irá conter:

dir/subdir/file1
dir/subdir/file2
tar cf - *

Esta tar usos para enviar * para stdout

|

Este faz o redirecionamento óbvia de stdout para ...

(cd <dest> ; tar xf - )

Este, que muda PWD para o local apropriado e, em seguida, extrai da entrada padrão

Eu não sei por que isso seria mais rápido do que o rsync, já que não há compressão envolvida.

A solução tar irá preservar links simbólicos, enquanto cp só vai fazer cópias e destruir as ligações.

tar tem sido um utilitário padrão Unix muito mais tempo do rsync. Você é mais provável para encontrá-lo em uma situação quando uma hierarquia de diretórios precisa ser copiado para outro local (mesmo outro computador). rsync é provavelmente mais fácil de usar estes dias, mas é mais lento porque compara a origem e destinos e sincronia são eles. tar apenas cópias em uma direção.

Se você tem GNU cp (que todos os sistemas baseados em Linux), o cp --archive vai funcionar, mesmo em arquivos de disco rígido ligadas, e alcatrão não é necessário.

Quando isso acontece, um colega de trabalho escreveu um comando quase idêntico em um dos nossos scripts. Depois que eu passei algum tempo intrigante sobre ele, eu perguntei por que ele tinha usado que ao invés de cp. Sua resposta, se bem me lembro, era que cp é lento ao fazer uma cópia de um sistema de arquivos para outro.

Se isso é ou não verdade exigiria mais testes do que eu gostaria de passar sobre a questão, mas ele faz um certo sentido. O primeiro processo tar lê a partir do dispositivo de origem o mais rapidamente possível apenas esperando por esse dispositivo para ler. Enquanto isso, o segundo processo tar lê de seu tubo de entrada e escreve o mais rápido possível. Ele pode ter que esperar para a entrada, mas se escreve sobre o dispositivo de destino são mais lentas do que lê no dispositivo de origem que só vai esperar no dispositivo de destino. Um comando único cp vai ter que esperar tanto a fonte e os dispositivos de destino.

Por outro lado, os sistemas operacionais modernos fazem um bom trabalho de operações de IO pré-cache. É inteiramente possível cp passará a maior parte de seu tempo de espera nas gravações e recebendo lê da memória, em vez do próprio dispositivo. Parece que seria necessário de dados muito sólidos para escolher usando dois comandos tar em vez do comando mais simples cp.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top