Интересное использование tar ... но что происходит? - PullRequest
10 голосов
/ 25 ноября 2008

Я видел следующее интересное использование tar в скриптах Bash коллеги:

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

Очевидно, это работает так же, как rsync -av, но быстрее. Возникает вопрос, как?

-m


РЕДАКТИРОВАТЬ : Кто-нибудь может объяснить , почему должно ли это решение быть предпочтительным по сравнению со следующим?

cp -rfp * dest

Первый быстрее?

Ответы [ 12 ]

12 голосов
/ 25 ноября 2008

Он записывает архив в стандартный вывод, затем передает его в подпроцесс - в скобках - который изменяется в другой каталог и считывает / извлекает из стандартного ввода. Вот что означает тире после аргумента f. Это в основном копирование всех видимых файлов и подкаталогов текущего каталога в другой каталог.

9 голосов
/ 25 ноября 2008

На разнице между cp и tar для копирования иерархий каталогов можно провести простой эксперимент, чтобы показать разницу:

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

Разница заключается в жестко связанных файлах. Обратите внимание, как жестко связанные файлы копируются индивидуально с cp и вместе с tar. Чтобы сделать разницу более очевидной, взгляните на иноды для каждого:

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

Возможно, есть и другие причины, чтобы предпочесть tar, но это одна большая причина, по крайней мере, если у вас много жестко связанных файлов.

5 голосов
/ 25 ноября 2008

Для каталога с 25 000 пустых файлов:

$ 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

Для каталога с 4 файлами по 1073741824 байта (1 ГБ) каждый

$ 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

Полагаю, это явление сильно зависит от файловой системы. Если я прав, вы увидите резкое различие между файловой системой, которая специализируется на многочисленных небольших файлах, таких как reiserfs 3.6, и файловой системой, которая лучше справляется с большими файлами.

(я запускал вышеупомянутые тесты на HFS +.)

2 голосов
/ 13 февраля 2011

Книга PowerTools имеет копию:

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

'&&' - это условие, которое проверяет код возврата предыдущей команды. То есть, если «cd» потерпел неудачу, «tar xf -» не будет выполнен. Я всегда добавляю -v (подробный) и -B (вход для повторной блокировки).

Я использую смолу все время. Это особенно полезно для копирования в удаленную систему, например:

tar cvf -. | ssh somebody @ somemachine '(где-то cd && tar xBf -)'

2 голосов
/ 25 ноября 2008

Это уникальное использование труб. По сути, первый tar обычно пишет напрямую в файл, но вместо этого он собирается записать в stdout (-), который затем перенаправляется в другой tar, который принимает stdin, а не файл. По сути, это то же самое, что записать в файл и распаковать позже, за исключением того, что между ними нет файла.

1 голос
/ 01 сентября 2009

Я полагаю, что tar выполнит операцию слияния в стиле Windows с глубоко вложенными каталогами, тогда как cp перезапишет подкаталоги.

Например, если у вас есть макет:

dir/subdir/file1

и вы копируете его в место назначения, содержащее:

dir/subdir/file2

Тогда с копией у вас останется:

dir/subdir/file1

Но с помощью команды tar ваш пункт назначения будет содержать:

dir/subdir/file1
dir/subdir/file2
1 голос
/ 25 ноября 2008

В некоторых старых версиях cp не было опций -f / -p (и аналогичных) для сохранения разрешений, поэтому этот трюк сделал эту работу.

1 голос
/ 25 ноября 2008
tar cf - * | (cd <dest> ; tar xf - )

собирается передать все не скрытые файлы / каталоги текущего каталога в stdout, а затем передать это в stdin нового субоболочки. Эта оболочка сначала меняет текущий рабочий каталог на <dest>, а затем распаковывает его в этот каталог.

0 голосов
/ 25 февраля 2009

Как оказалось, сотрудник написал почти идентичную команду в одном из наших сценариев. Потратив некоторое время на размышления, я спросил, почему он использовал это, а не cp. Насколько я помню, он ответил, что cp работает медленно при копировании из одной файловой системы в другую.

Правдиво это или нет, потребует больше испытаний, чем я собираюсь потратить на этот вопрос, но это имеет определенный смысл. Первый процесс tar читает с исходного устройства как можно быстрее, ожидая только чтения этого устройства. Между тем, второй процесс tar читает из своего канала ввода и пишет как можно быстрее. Возможно, придется ждать ввода, но если запись на целевом устройстве выполняется медленнее, чем на исходном устройстве, он будет ожидать только на целевом устройстве. Одной команде cp придется ждать как на исходном, так и на целевом устройствах.

С другой стороны, современные операционные системы довольно хорошо справляются с предварительным кэшированием операций ввода-вывода. Вполне возможно, что cp будет тратить большую часть своего времени на ожидание записи и считывания из памяти, а не самого устройства. Похоже, что для выбора нужно действительно надежные данные, используя две команды tar, а не более простую команду cp.

0 голосов
/ 14 января 2009

Если у вас есть GNU cp (который будет работать во всех системах на основе Linux), cp --archive будет работать даже для жестко связанных файлов, и tar не нужен.

...