巨大なファイルを扱おうとすると、環境によってはクォータなどの影響を受けて取り回しが悪いことがある。 今回は、そんなときに split コマンドで一つのファイルを複数にばらして扱う方法について。 ここでは macOS を使ったけど GNU/Linux でも同じやり方ができる。
使った環境は次の通り。
$ sw_vers ProductName: Mac OS X ProductVersion: 10.12.6 BuildVersion: 16G1212 $ python --version Python 3.6.4
バイナリファイルを分割する
まずは分割するために大きなバイナリファイルを用意する。
ゼロフィルされたものだと連結したとき壊れていないか確かめにくいのでランダムな値で構成した。
具体的には dd
コマンドで入力を /dev/random
デバイスにする。
$ dd if=/dev/random of=largefile bs=1m count=1000 1000+0 records in 1000+0 records out 1048576000 bytes transferred in 100.697699 secs (10413108 bytes/sec)
これでランダムな値の詰まった 1GB のバイナリファイルができた。 連結したときに内容が変わっていないか確かめるため MD5 のハッシュ値を確認しておこう。
$ ls -alF largefile -rw-r--r-- 1 amedama staff 1048576000 2 10 19:08 largefile $ md5 largefile MD5 (largefile) = 98fc2a9a7a18d9c8907662a88fb238c8
続いて分割したファイルを入れるディレクトリを用意する。
$ mkdir -p splits
そして split
コマンドを使って先ほど作ったバイナリファイルを 100MB ずつに分割する。
バイナリファイルでは -b
オプションを指定することで分割サイズが指定できる。
第一引数には分割するファイルを、第二引数には分割したファイルの保存先を指定する。
分割したファイルには後ろにアルファベットがつくので、ドットで終わるようにしておくと後から扱いやすくなる。
$ split -b 100m largefile splits/largefile.
分割したファイルはこんな感じ。
$ ls -alF splits total 2048000 drwxr-xr-x 12 amedama staff 408 2 10 19:09 ./ drwxr-xr-x 6 amedama staff 204 2 10 19:09 ../ -rw-r--r-- 1 amedama staff 104857600 2 10 19:09 largefile.aa -rw-r--r-- 1 amedama staff 104857600 2 10 19:09 largefile.ab -rw-r--r-- 1 amedama staff 104857600 2 10 19:09 largefile.ac -rw-r--r-- 1 amedama staff 104857600 2 10 19:09 largefile.ad -rw-r--r-- 1 amedama staff 104857600 2 10 19:09 largefile.ae -rw-r--r-- 1 amedama staff 104857600 2 10 19:09 largefile.af -rw-r--r-- 1 amedama staff 104857600 2 10 19:09 largefile.ag -rw-r--r-- 1 amedama staff 104857600 2 10 19:09 largefile.ah -rw-r--r-- 1 amedama staff 104857600 2 10 19:09 largefile.ai -rw-r--r-- 1 amedama staff 104857600 2 10 19:09 largefile.aj
分割したら、後はもちろん連結して元に戻すことになる。
split
コマンドで分割したファイルは cat
コマンドで連結できる。
ようするに順番に内容を出力して、それをファイルにリダイレクトするだけ。
$ cat splits/largefile.* > largefile.restored
分割したファイルを一つに連結したファイルができた。
$ ls -alF largefile.restored -rw-r--r-- 1 amedama staff 1048576000 2 10 19:09 largefile.restored
連結したファイルのハッシュ値を確認しておこう。 この値が分割する前のファイルと一致していれば、内容は変わっていないことが分かる。
$ md5 largefile.restored MD5 (largefile.restored) = 98fc2a9a7a18d9c8907662a88fb238c8
ハッシュ値は一致するので分割前と分割・連結後で内容は変わっていないことが分かった。
テキストファイルを分割する
先ほどはファイルをバイト単位で分割したけど、テキストファイルとして扱って行数で分割することもできる。 今度はそれを試してみよう。
先ほどと同様、ランダムな値の入ったテキストファイルを用意したい。 今回は Python を使って作ってみることにしよう。
$ python
以下のスニペットで、ランダムな 10 桁の数値が 10000 行連続するテキストファイルを作ってみた。
>>> import random >>> with open('largefile.txt', 'w') as f: ... for _ in range(10000): ... line = '{:010d}\n'.format(random.randint(0, 9999999999)) ... while True: ... wrote = f.write(line) ... if wrote == len(line): ... break ... line = line[wrote:] ...
こんな感じのファイルができる。
$ ls -alF largefile.txt -rw-r--r-- 1 amedama staff 110000 2 10 19:47 largefile.txt $ head largefile.txt 2959925144 8203396354 9888228717 0217007087 6089181232 0800076687 8748631182 4433119315 5389404148 7941794927
先ほどと同じように、連結後のファイルと比較するためのハッシュ値を確認しておこう。
$ md5 largefile.txt MD5 (largefile.txt) = 6b98e9d1ec56869609c5cfa29c996f5a
一旦、先ほど分割したファイルはお掃除しておく。
$ rm -rf splits/*
その上でファイルを分割する。
テキストファイルの場合は -l
オプションで分割する行数を指定する。
$ split -l 1000 largefile.txt splits/largefile.txt.
このようにファイルが分割された。
$ ls -alF splits total 240 drwxr-xr-x 12 amedama staff 408 2 10 19:49 ./ drwxr-xr-x 5 amedama staff 170 2 10 19:49 ../ -rw-r--r-- 1 amedama staff 11000 2 10 19:49 largefile.txt.aa -rw-r--r-- 1 amedama staff 11000 2 10 19:49 largefile.txt.ab -rw-r--r-- 1 amedama staff 11000 2 10 19:49 largefile.txt.ac -rw-r--r-- 1 amedama staff 11000 2 10 19:49 largefile.txt.ad -rw-r--r-- 1 amedama staff 11000 2 10 19:49 largefile.txt.ae -rw-r--r-- 1 amedama staff 11000 2 10 19:49 largefile.txt.af -rw-r--r-- 1 amedama staff 11000 2 10 19:49 largefile.txt.ag -rw-r--r-- 1 amedama staff 11000 2 10 19:49 largefile.txt.ah -rw-r--r-- 1 amedama staff 11000 2 10 19:49 largefile.txt.ai -rw-r--r-- 1 amedama staff 11000 2 10 19:49 largefile.txt.aj
wc
コマンドで確認すると、ちゃんとそれぞれ 1000 行ずつに分割されているようだ。
$ wc -l splits/largefile.txt.aa
1000 splits/largefile.txt.aa
続いては分割したファイルを連結する。 やり方はバイト単位で分割したときと同じ。
$ cat splits/largefile.txt.* > largefile.restored.txt
連結できた。
$ ls -alF largefile.restored.txt -rw-r--r-- 1 amedama staff 110000 2 10 19:50 largefile.restored.txt
ハッシュ値を確認しよう。 分割前のハッシュ値と一致しているため、分割・連結後も内容が変わっていないことが分かる。
$ md5 largefile.restored.txt MD5 (largefile.restored.txt) = 6b98e9d1ec56869609c5cfa29c996f5a
めでたしめでたし。
スマートPythonプログラミング: Pythonのより良い書き方を学ぶ
- 作者: もみじあめ
- 発売日: 2016/03/12
- メディア: Kindle版
- この商品を含むブログ (1件) を見る