12

同僚の Bash スクリプトで、次の興味深い tar の使用法を見ました。

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

どうやら rsync -av と同じように動作しますが、より高速です。どうやって?という疑問が生じます。

-m


編集:このソリューションが以下よりも望ましい理由を誰かが説明できますか?

cp -rfp * dest

前者の方が速いですか?

4

12 に答える 12

13

アーカイブを標準出力に書き込み、それをサブプロセス (括弧で囲まれている) にパイプします。サブプロセスは別のディレクトリに移動し、標準入力から読み取り/抽出します。fそれが、引数の後のダッシュ文字の意味です。基本的に、現在のディレクトリのすべての可視ファイルとサブディレクトリを別のディレクトリにコピーしています。

于 2008-11-25T01:11:56.163 に答える
9

ディレクトリ階層をコピーするための 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ください。違いをより明確にするために、それぞれの inode を見てください。

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 を好む理由は他にもあると思いますが、これは大きな理由の 1 つです。

于 2008-11-25T04:10:25.850 に答える
7

25,000 個の空のファイルがあるディレクトリの場合:

$ time { tar -cf - * | (cd ../bar; tar -xf - ); }
実質 0m4.209s
ユーザー 0分0.724秒
システム 0m3.380s

$ 時間 { cp * ../baz/; }
実質 0m18.727s
ユーザー 0分0.644秒
システム 0 分 7.127 秒

それぞれ 1073741824 バイト (1GB) のファイルが 4 つあるディレクトリの場合

$ time { tar -cf - * | (cd ../bar; tar -xf - ); }
実質 3m44.007s
ユーザー 0m3.390s
システム 0m25.644s

$ 時間 { cp * ../baz/; }
実質 3 分 11.197 秒
ユーザー 0m0.023s
システム 0 分 9.576 秒

私の推測では、この現象はファイルシステムに大きく依存しています。私が正しければ、reiserfs 3.6 などの多数の小さなファイルに特化したファイルシステムと、大きなファイルの処理に優れたファイルシステムとの間には劇的な違いがあることがわかります。

(上記のテストは HFS+ で実行しました。)

于 2008-11-25T02:59:40.143 に答える
2

PowerToolsブックには、次のようなコピーがあります。

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

'&&'は、前のコマンドの戻りコードをチェックする条件です。つまり、「cd」が失敗した場合、「tarxf-」は実行されません。私は常に-v(冗長)と-B(再ブロック入力)をスローします。

私はいつもtarを使っています。これは、次のようなリモートシステムにコピーする場合に特に便利です。

tarcvf-。| ssh some @ somemachine'(cd somewhere && tar xBf-)'

于 2011-02-13T00:58:21.700 に答える
2

これはパイプのユニークな使い方です。基本的に、最初の tar は通常、ファイルに直接書き込みますが、代わりに stdout (-) に書き込みます。これは、ファイルではなく stdin を取る他の tar にリダイレクトされます。基本的に、これはファイルに tar して後で untar するのと同じことですが、その間にファイルがありません。

于 2008-11-25T01:13:00.640 に答える
1

一部の古いバージョンのcpには、権限を保持するための-f / -p(および同様の)オプションがなかったため、このtarトリックが機能しました。

于 2008-11-25T03:26:54.003 に答える
1

tar は、深くネストされたディレクトリで Windows スタイルの「マージ」操作を実行するのに対し、cp はサブディレクトリを上書きすると思います。

たとえば、レイアウトがある場合:

dir/subdir/file1

そして、それを次を含む宛先にコピーします。

dir/subdir/file2

次に、コピーを使用すると、次のものが残ります。

dir/subdir/file1

ただし、tar コマンドを使用すると、宛先に次のものが含まれます。

dir/subdir/file1
dir/subdir/file2
于 2009-09-01T19:28:43.253 に答える
1
tar cf - * | (cd <dest> ; tar xf - )

現在のディレクトリの隠しファイル/ディレクトリ以外のすべてを標準出力にtarし、それを新しいサブシェルの標準入力にパイプします。そのシェルは、最初に現在の作業ディレクトリを に変更し<dest>、次にそのディレクトリに untar します。

于 2008-11-25T01:13:08.360 に答える
0

tar ソリューションはシンボリック リンクを保持しますが、cp は単にコピーを作成してリンクを破棄します。

tar は、rsync よりもはるかに長い間、標準の Unix ユーティリティでした。ディレクトリ階層を別の場所 (別のコンピュータであっても) にコピーする必要がある場合に、この問題が発生する可能性が高くなります。最近は rsync の方が使いやすいかもしれませんが、ソースと宛先の両方を比較して同期するため遅くなります。tar は一方向にコピーするだけです。

于 2008-11-25T05:07:50.243 に答える
0

GNU cp(すべての Linux ベースのシステム) を使用してcp --archiveいる場合は、ハードリンクされたファイルでも動作し、tar は必要ありません。

于 2009-01-14T11:40:56.973 に答える
0

たまたま、同僚がスクリプトの 1 つにほぼ同じコマンドを書き込んでしまいました。私はそれについてしばらく戸惑った後、なぜ彼が ではなくそれを使用したのか尋ねましたcp. 私が覚えているように、彼の答えは、cpあるファイルシステムから別のファイルシステムへのコピーを作成するときに遅いというものでした。

これが真実であるかどうかは、私が質問に費やすよりも多くのテストを必要とするでしょうが、それはある程度理にかなっています. 最初のtarプロセスは、ソース デバイスから可能な限り迅速に読み取りますが、そのデバイスが読み取られるのを待つだけです。一方、2 番目のtarプロセスは入力パイプからの読み取りと書き込みをできるだけ迅速に行います。入力を待機する必要がある場合がありますが、宛先デバイスでの書き込みがソース デバイスでの読み取りよりも遅い場合は、宛先デバイスでのみ待機します。単一のcpコマンドは、送信元デバイスと宛先デバイスの両方で待機する必要があります。

一方、最新のオペレーティング システムは、IO 操作を事前にキャッシュするという点で非常に優れています。cpデバイス自体ではなく、書き込みの待機とメモリからの読み取りにほとんどの時間を費やす可能性は十分にあります。tarより単純なコマンドではなく、2 つのコマンドを使用して選択するには、非常に確かなデータが必要なようcpです。

于 2009-02-25T00:57:35.727 に答える
0
tar cf - *

これは tar を使用して * を stdout に送信します

|

これにより、stdout の明らかなリダイレクトが行われます...

(cd <dest> ; tar xf - )

これにより、PWD が適切な場所に変更され、標準入力から抽出されます。

圧縮が含まれていないため、なぜこれがrsyncよりも高速になるのかわかりません。

于 2008-11-25T01:15:09.027 に答える