ファイルを分割した後、再びファイルを結合する最良の方法は何ですか?


73

大きなファイルがあり、それを100メガバイトのチャンクに分割する必要がある場合は、

split -b 100m myImage.iso

それは通常私に何かを与えます

xaa
xab
xac
xad

そしてそれらを元に戻すために私は使用しています

cat x* > myImage.iso

ファイルのグループ内のコードの各行を読み取りcat、出力を新しいファイルにリダイレクトするよりも効率的な方法があるはずです。2つのファイルを開いEOFて、最初のファイルからマーカーを削除し、それらを接続する方法のように-すべてのコンテンツを確認する必要はありません。

Windows / DOSには、バイナリファイルのコピーコマンドがあります。ヘルプには、このコマンドが複数のファイルを結合できるように設計されていることが記載されています。次の構文で動作します:(/bバイナリモード用)

copy /b file1 + file2 + file3 outputfile

Linuxでcatよりも大きなファイルを結合するのに似た、またはより良い方法はありますか?

更新

cat実際には、ファイルを結合する正しい方法であり、最良の方法であると思われます。私がずっと正しいコマンドを使っていたことを知ってうれしい:)フィードバックをありがとう。


22
サイドノート:cat x*ファイルの順序はロケール設定に依存するため、を使用しないでください。より良いタイピングを開始cat xプレスよりも、Escキーとその後*-あなたはファイルの拡張された順に表示されますし、並べ替えることができます。
rozcietrzewiacz

16
代わりにcat x*、あなたは、シェルブレース展開、検討することもできcat xa{a..g}に指定されたシーケンスを展開するcat のXaaをXAB XAC XAD XAE XAF XAG
Peter.O

3
@rozcietrzewiacz-壊れるロケール設定をどのように調整するかの例を教えていただけますcat x*か?新しいロケール設定にも影響を与えないsplit場合ようにsplitしてcat x*、同じシステム上で使用された、彼らは常に働くだろうか?
cwd

3
「最初の1からEOFマーカーを削除し、2つのファイルを開くと、それらを接続する- 。すべての内容を経由せず、」あなたは、あなたがやりたいことのために新しいファイルシステムを考案する必要がありますように...聞こえる
JoelFan

6
@cwd:split.cGNU Coreutilsを見ると、サフィックスは文字の固定配列から構成されていますstatic char const *suffix_alphabet = "abcdefghijklmnopqrstuvwxyz";。サフィックスはロケールの影響を受けません。(しかし、正しいロケールでは小文字が並べ替えられるとは思わない。EBCDICでさえ標準の順序を維持している。)
キーストンプソン

回答:


50

それはまさにそのcatために作られたものです。これは最も古いGNUツールの1つであるため、他のツールがこれほど速く/より良いことを行うことはほとんどないと思います。そして、それはパイプではありません-出力をリダイレクトするだけです。


cat x, then press Escあなたが言及したトリックきちんとしている..私はそのような何かを探してきた、おかげで...良いコメントと良い答え
Peter.O

2
どういたしまして:)また、コマンドラインにファイルのリストがある場合は、を使用Ctrl+Wして単語を切り取りCtrl+Y、貼り付けることができます。
rozcietrzewiacz

猫は「連結」を意味します
ジョエルファン

4
..および "catenate"は、 "チェーン"を意味するラテン語の "catena"から派生しています。連結は、チェーンのリンクを結合することです。...(ビットさらにオフトピック、カテナリー曲線はまた、「カテナ」からderrivesそれは方法鎖ハングである。)
Peter.O

19

フードの下

最初のファイルをコピーし、その後に2番目のファイルをコピーするなど、効率的な方法はありません。DOS copycatそれの両方。

各ファイルは、ディスク上の他のファイルとは独立して保存されます。ディスクのようなデバイスにデータを保存するように設計されたほとんどすべてのファイルシステムは、ブロックごとに動作します。発生する状況の非常に単純化されたプレゼンテーションを次に示します。ディスクは、たとえば1kBのブロックに分割され、ファイルごとにオペレーティングシステムがそれを構成するブロックのリストを保存します。ほとんどのファイルは整数ブロック長ではないため、最後のブロックは部分的にしか占有されていません。実際には、ファイルシステムには、複数のファイル間で最後の部分ブロックを共有したり、「ブロック46798、ブロック46799、…」ではなく「ブロック46798〜47913」を保存するなど、多くの最適化があります。オペレーティングシステムが新しいファイルを作成する必要がある場合、空きブロックを探します。ブロックは連続している必要はありません。ブロック4、5、98、および178のみが空いている場合でも、4kBファイルを保存できます。

ファイルの途中で部分ブロックをサポートすることもできますが、特にファイルに非連続的にアクセスする場合はかなり複雑になります。10340番目のバイトにジャンプするには、11番目のブロックの100番目のバイトにジャンプできなくなります。すべての介在ブロックの長さをチェックします。

ブロックの使用を考えると、一般的に最初のファイルはブロックの中間で終わるため、2つのファイルを結合することはできません。もちろん、特別な場合もありますが、連結時に両方のファイルを削除したい場合のみです。これは、まれな操作に対する非常に具体的な処理になります。典型的なファイルシステムでは、多くのファイルが同時にアクセスされるため、このような特別な処理は単独では実行されません。したがって、最適化を追加する場合は、慎重に考える必要があります。他のプロセスが関連するファイルの1つを読み取っている場合はどうなりますか?誰かがAとCを連結している間に誰かがAとBを連結しようとするとどうなりますか?等々。全体として、このまれな最適化は大きな負担になります。

全体として、他の場所で大きな犠牲を払わなければ、ファイルの結合をより効率的にすることはできません。それはそれだけの価値はありません。

分割と結合について

splitそしてcat、ファイルを分割し、参加の簡単な方法です。splitアルファベット順に名前が付けられたファイルを作成するので、cat *結合に役立ちます。

cat結合の欠点は、一般的な障害モードに対して堅牢ではないことです。ファイルの1つが切り捨てられたり欠落したりしても、cat文句を言わず、出力が破損するだけです。

以下のようなマルチパートアーカイブ、生産圧縮ユーティリティがあるzipsplitとはrar -v。それらは、分割に加えて圧縮およびパック(複数のファイルを1つに組み立てる)(および逆に結合に加えて解凍および解凍)するため、あまりユニキシではありません。ただし、すべての部品が揃っていること、および部品が完全であることを確認するという点で便利です。


8

システムのstdin/ を通してすべてのコンテンツをパイプするよりも効率的な方法があるはずのようですstdout

それが実際に起こっていることではないことを除いて。シェルは、stdoutを開いているファイルにcat 直接接続しています。つまり、「stdoutを経由する」ことは、ディスクへの書き込みと同じです。


catを使用してコンソールに数ギガバイトのコードを表示し、それをキャプチャしてファイルに入れることを想像していました。これは、catを使用して、表示できない出力をリダイレクトするときに何が起きなければならないかについての精神的なイメージです。2つのファイルを開き、それらを接続し、それらを閉じる方法があれば、すべてのコード行を実行するよりも効率的であるように見えましたcat。直接接続について教えてくれてありがとう。
cwd

@cwd 2つのファイルをそのように結合できるファイルシステムを設計することは可能ですが、それはファイルシステムの設計を非常に複雑にします。多くの一般的なタスクをより複雑で遅くすることを犠牲にして、その1つの操作に対して最適化する必要があります。
ジル

@Gilles-低レベルの詳細についてもっと知りたいと思うでしょう。私にとっては、いくつかのファイルについてハードディスクからすべてのセクターを読み取り、それらをディスク上の他の未使用セクターにダンプするのは非効率的です。そして、それらを格納するのに十分なブロックが常に並んでいるとは限らない可能性があるため、大きなファイルは、空きセクタの複数のブロックにわたって格納する必要があると思います。したがって、理論的には、EOFマーカーを削除し、次のファイルの開始時にセクターのグループをポイントすることにより、ファイルを1つに結合できます。* nixは強力なので、猫よりも良い方法があるのだろうかと思いました。
cwd

@cwd「EOFマーカー」はありません。正常な最新のファイルシステムは、ファイル内で一部の文字が発生するのを防ぎます(または、複雑なエンコーディングが必要です)。しかし、EOFマーカーがあったとしても、ほとんどの場合、その後に正しいファイルはありません。
ジル

私は実際のEOFマーカーではなくEOFマーカーの概念を意味しました。それ以外の場合、ハードドライブ上のファイルのビットとバイトを見ると、それがどこで終わるのかをどのように知るのですか?ファイルの開始時にファイルの長さを指定しますか?私は非常に低レベルのものについて話している。それもあなたが言っていることですか?
cwd

3

私はかつてまさにこの問題を抱えていました。いくつかのファイルを結合したかったのですが、それらを二重に保持するのに十分なディスク容量がありませんでした。

だから私はたくさんのプログラムを書いた:

  • ファイルを読み取り、stdoutに送信し、終了したら削除することにより、ファイルを「吸い上げる」
  • そして、「オンザフライ」でデータをバッファリングします。

これにより、次のようなことができるようになりました

partto sourcefile | mybuffer 128M >>cumufile

したがって、128Mがまだ書き込まれていない間にソースファイルを削除しました。少し危険ですが、データがそれほど貴重ではない場合、またはデータが他の場所にも存在する場合は実行可能です。

必要に応じて、ソースを提供できます。


0

技術的に言えば、これはコンテンツ全体を読み書きすることなくファイル全体にアクセスする方法であり、巨大なファイルや空き容量が少ない場合に役立ちます。

$ mkfifo myImage.iso
$ cat xa{a..g} > myImage.iso &

そして、myImage.iso例えば、

$ md5sum myImage.iso

もちろんmyImage.iso、特別なファイル(名前付きパイプ)であり、通常のファイルではありません。そのため、これは、あなたがしようとしていることに依存して、役に立つかもしれません。


0

ファイル分割

サイズで分割

大きなファイルを小さなファイルに分割し、小さな出力ファイルの名前とサイズを選択する場合、これが方法です。

split -b 500M videos\BigVideoFile.avi SmallFile.

この方法で、1つの大きなファイルを500 MBの小さな部分に分割することを選択します。また、パーツファイルの名前はSmallFileにする必要があります。ファイル名の後にドットが必要なことに注意してください。その結果、次のような新しいファイルが生成されます。

SmallFile.ab SmallFile.ad SmallFile.af SmallFile.ah SmallFile.aj
SmallFile.aa SmallFile.ac SmallFile.ae SmallFile.ag SmallFile.ai SmallFile.ak
...

行数で分割

この方法では、テキストファイルを50行に制限された小さなファイルに分割します。

split -l 50 text_to_split.txt

結果は次のようになります。

xaa xab xac ...

バイトで分割

バイト単位の小さなファイルのカスタムサイズで小さなファイルに分割します。

split -b 2048 BigFile.mp4

結果は、「行数で分割」の結果に似ているはずです。

ファイル結合

2つの方法でファイルを結合できます。最初のものは:

cat SmallFile.* > OutputBigVideoFile.avi

または:

cat SmallFile.?? > OutputBigVideoFile.avi

注:ファイルを結合する場合、小さなファイルが破損しないようにしてください。また、すべての小さな(部分)ファイルは同じディレクトリにある必要があります。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.