8

連結したい 2 つの巨大なファイル (数 GB) があり、空きディスク容量がほとんどない (数百 MB としましょう) とします。つまり、与えられたfile1と、バイトごとに連結して一緒file2にした結果である単一のファイルになり、元のファイルを削除します。file1file2

cat file2 >> file1; rm file22 つの操作の合間にディスク容量が不足するため、明らかな を行うことはできません。

無料または非無料のツールを使用したあらゆるプラットフォームでのソリューションを歓迎します。これは、先日 Linux ISO をダウンロードしているときに思いついた架空の問題で、ワイヤレスの問題によりダウンロードが途中で中断されました。

4

15 に答える 15

15

ディスク セクタのシャッフルとファイル チェーンの操作を含む巧妙な解決策を見つけるのに費やした時間: 2 ~ 4 時間

インプレース コピーと切り捨てを行うソフトウェアの取得/作成に費やした時間: 2 ~ 20 時間

プログラマー率の中央値 50 ドル/時間の倍: 400 ドルから 1200 ドル

1TB USB ドライブのコスト: $100-$200

「機会費用」という言葉を理解する能力:プライスレス

于 2008-11-14T17:23:51.543 に答える
9

難しいのは、元のファイルからスペースを回復する方法を決定することだと思います。

私は次のことがうまくいくと思います:

  1. 結合したサイズのスパース ファイルを割り当てます。
  2. 2 番目のファイルの末尾から新しいファイルの末尾まで 100Mb をコピーします。
  3. 2 番目のファイルの末尾の 100Mb を切り捨てます
  4. 2 番目のファイルが終了するまで 2 と 3 をループします (2. を宛先ファイルの正しい場所に変更します)。
  5. 2&3&4 を実行しますが、最初のファイルを使用します。

これはすべて、スパース ファイルのサポートに依存しており、ファイルの切り捨てによってスペースがすぐに解放されます。

実際にこれを実行したい場合は、ddコマンドを調査する必要があります。コピーステップを実行できる

別の回答の誰かが、スパースファイルを必要としないが、file2を2回コピーするきちんとしたソリューションを提供しました:

  1. ファイル 2 の末尾から 100Mb のチャンクを新しいファイル 3 にコピーし、逆の順序で終了します。途中でファイル 2 を切り捨てます。
  2. ファイル 3 の最後から 100Mb のチャンクをファイル 1 にコピーし、元の順序でファイル 1 の最後にチャンクを配置します。ファイル 3 を途中で切り捨てます。
于 2008-11-14T16:59:11.483 に答える
7

これが私の最初の答えに対するわずかな改善です。

100MBの空き容量がある場合は、2番目のファイルから最後の100MBをコピーして、3番目のファイルを作成します。2番目のファイルを切り捨てて、100MB小さくします。2番目のファイルが完全に個々の100MBチャンクに分解されるまで、このプロセスを繰り返します。

これで、これらの100MBファイルのそれぞれを最初のファイルに一度に1つずつ追加できます。

于 2008-11-14T17:56:47.780 に答える
4

これらの制約により、ファイル システムを改ざんする必要があると思います。ファイルサイズと割り当てブロックを直接編集します。

つまり、ファイル コンテンツのブロックをシャッフルする必要はなく、それらのファイルに関する情報を編集するだけです。

于 2008-11-14T16:53:32.413 に答える
2

ファイルの圧縮性が高い場合 (ログなど):

gzip file1

gzip file2

zcat file1 file2 | gzip > file3

rm file1

rm file2

gunzip file3
于 2009-07-24T23:04:34.527 に答える
1

明らかに、経済的な答えは、それが可能な答えであると仮定して、より多くのストレージを購入することです。ただし、ストレージを追加する方法がない、または機器自体にアクセスできない組み込みシステムではない場合があります。たとえば、飛行中の宇宙探査機です。

スパースファイルシステムを使用している場合は、スパースファイルシステムに基づいて以前に提示された回答が適切です(問題が発生した場合の破壊的な性質を除く)。しかし、そうでない場合はどうなりますか?

ファイルの終わりから始めて、2つのコピーブロックをターゲットファイルの最初までコピーして、それらを逆にします。各ブロックの後で、ソースファイルをコピーされていない長さに切り捨てます。ファイル#1について繰り返します。

この時点で、ターゲットファイルにはすべてのデータが逆方向に含まれ、ソースファイルはなくなります。

タルトとターゲットファイルの最後からブロックを読み取り、それらを逆にして、もう一方が来た場所に書き込みます。ブロックを弾いて内側に向かって作業します。

完了すると、ターゲットファイルはソースファイルの連結になります。スパースファイルシステムは必要ありません。ファイルシステムをいじる必要もありません。データをメモリに保持できるため、これはゼロバイトの空き容量で実行できます。

于 2008-11-14T17:45:07.053 に答える
1

わかりました、理論的な娯楽のために、実際に時間を無駄にしないと約束した場合にのみ:

  • ファイルは分割してディスクに保存されます
  • ピースはチェーンでリンクされています

したがって、次の方法でファイルを連結できます。

  • 最初のファイルの最後の部分を最後のファイルの最初の部分にリンクする
  • 最初のファイルのディレクトリ エントリを変更して、最後の部分とファイル サイズを変更する
  • 最後のファイルのディレクトリ エントリを削除する
  • 最初のファイルのファイルの終わりマーカーがあれば、それをクリーンアップします
  • 最初のファイルの最後のセグメントが部分的にしか満たされていない場合は、ファイルの途中にゴミが入らないように、最後のファイルのセグメントにデータをコピーする必要があることに注意してください [@Wedge に感謝します!]

これは最適に効率的です: 最小限の変更、最小限のコピー、予備のディスク領域は必要ありません。

今すぐUSBドライブを購入してください;-)

于 2008-11-14T17:30:55.147 に答える
1

あまり効率的ではありませんが、できると思います。

最初のファイルを追加モードで開き、ディスクがほぼいっぱいになるまで、2 番目のファイルからそれにブロックをコピーします。2 番目のファイルの残りの部分については、ランダム アクセス I/O を使用して、停止したポイントからファイルの先頭までブロックをコピーします。最後のブロックをコピーした後、ファイルを切り捨てます。完了するまで繰り返します。

于 2008-11-14T17:30:17.270 に答える
1

軽率に聞こえるかもしれませんが、より大きなディスクを入手するというオプションを検討しましたか? その方が早いかも…。

于 2008-11-14T17:01:03.117 に答える
0

ファイル システム全体を圧縮することで、容量を確保できる場合があります。私は NTFS がこれをサポートしていると信じており、それをサポートする *nix ファイル システムのフレーバーがあると確信しています。また、ファイルをコピーした後でも、開始時よりも多くのディスク容量が残っているという利点があります。

于 2008-11-14T21:36:40.363 に答える
0

OK、問題を少し変更します。ディスクには必要のないものが他にもある可能性がありますが、それが何であるか、どこにあるかはわかりません。見つけたら削除すれば、十分な空き容量が得られるかもしれません。

これらの「腫瘍」を見つけるために、いくつかの大きなものであろうと小さなものであろうと、私は小さなサンプリング プログラムを使用します。ディレクトリの先頭 (またはルート) から開始して、2 つのパスを作成します。パス 1 では、ディレクトリ ツリーをたどり、すべてのファイルのサイズを合計して合計 N バイトを取得します。パス 2 では、すべてのファイルを読み取っているふりをして、ディレクトリ ツリーを再度調べます。N/20 バイトを渡すたびに、「読み取り中」のディレクトリ パスとファイル名を出力します。したがって、最終的な結果は、ディレクトリの下のすべてのバイトに均等に分散されたパス名の 20 の深いサンプルになります。

次に、必要のないものがたくさん表示されるリストを見て、それを吹き飛ばしてください.

(これは、パフォーマンスの最適化に使用するサンプリング方法と同等のスペースです。)

于 2008-11-19T04:33:55.103 に答える
0

2つの考え:

十分な物理 RAM がある場合は、実際に 2 番目のファイルを完全にメモリに読み込んで削除し、追加モードで最初のファイルに書き込むことができます。もちろん、削除後、書き込みが完了する前に電源が切れた場合は、2 番目のファイルの一部が永久に失われます。

OS 機能 (仮想メモリ、「ごみ箱」など) によって使用されるディスク容量を一時的に減らします。おそらくWindowsでのみ使用されます。

于 2008-11-14T17:10:40.180 に答える
0

これが質問に対する直接的な答えであるとは思えません。これは、問題を解決する別の方法と考えることができます。

2番目のファイルは最初のファイルのパート2と考えてよいと思います。通常、zip アプリケーションでは、巨大なファイルが複数の部分に分割されていることがわかります。最初のパーツを開くと、アプリケーションは後続の処理で他のパーツを自動的に考慮します。

ここで同じことをシミュレートできます。@edgが指摘したように、ファイルシステムをいじるのは1つの方法です。

于 2008-11-14T17:12:05.030 に答える
0

あなたはこれを行うことができます:

head file2 --bytes=1024 >> file1 && tail --bytes=+1024 file2 >file2 

余分なディスク容量に応じて 1024 を増やすことができ、すべてのバイトが移動されるまでこれを繰り返します。

これはおそらく最速の方法です(開発時間の点で)

于 2008-11-14T21:19:36.730 に答える
-1

「フィーマップ」

http://www.mjmwired.net/kernel/Documentation/filesystems/fiemap.txt

于 2010-02-03T03:07:51.640 に答える