👏

splitコマンドでファイルを分割する方法について

に公開

今回はファイルを分割するためのsplitコマンドについて調べてみました。行数が多いファイルを分割する方法を調べていたら組み込みのコマンドとして存在していたので調べてみました。

splitコマンドの使い方

それでは早速splitコマンドを使ってみます。

検証用データの作成

今回はテストように100万行あるデータを作成してみました。Pythonでパパッと作りました。

with open("original.txt", "w") as f:
    for i in range(1_000_000):
        f.write(f"{i}\n")

これを実行すると、0から99,9999までの数字が入ったoriginal.txtファイルが生成されます。

早速分割してみる

それでは早速このファイルに対してsplitコマンドを実行させてみましょう。利用方法ですが、以下のようにsplit ファイル名のようにすると実行できます。

split original.txt

ただし、今回用意したファイルを実行すると以下のようなエラーが発生します。

split: too many files

理由ですが、デフォルトでは1,000行ずつでファイルを区切るようになっているのですが、今回は100万行あり分割数が大きすぎるためエラーが発生しました(後ほど回避策を載せます)。そのような場合は-lオプションで分割基準の行数を変更できます。試しに10万行ずつで区切るようにさせましょう。

split -l 100000 original.txt

実行すると、以下のように10の新しいファイルが生成されます。

.rw-r--r--@ 6.9M user 31 Oct 20:33 original.txt
.rw-r--r--@ 589k user 31 Oct 20:46 xaa
.rw-r--r--@ 700k user 31 Oct 20:46 xab
.rw-r--r--@ 700k user 31 Oct 20:46 xac
.rw-r--r--@ 700k user 31 Oct 20:46 xad
.rw-r--r--@ 700k user 31 Oct 20:46 xae
.rw-r--r--@ 700k user 31 Oct 20:46 xaf
.rw-r--r--@ 700k user 31 Oct 20:46 xag
.rw-r--r--@ 700k user 31 Oct 20:46 xah
.rw-r--r--@ 700k user 31 Oct 20:46 xai
.rw-r--r--@ 700k user 31 Oct 20:46 xaj

ファイル名をみるとxaa~xajのように謎のファイル名になっています。これはアルファベット順に分割されたファイルが格納されています。試しにxaaの最初と最後を見ると、以下のようにデータが0から99999まであることが確認でき、10万行入っていることも確認できます。

0
1
2
3
4
5
6
7
8
9
10
...
99990
99991
99992
99993
99994
99995
99996
99997
99998
99999

保存されるファイル名の変更

先ほどの例ではxaaのように元のファイル名の名残もないファイル名になっていました。基本的に分割されるデータについてはxaaのような命名にはなるものの、接頭辞を定義することができ、以下のように分割対象のファイル名の次に接頭辞を書けば対応できます。

split -l 100000 original.txt splitted-

試しに上記を実行すると、以下のようなファイル構成で生成されます。

.rw-r--r--@ 6.9M user 31 Oct 20:33 original.txt
.rw-r--r--@ 589k user 31 Oct 20:49 splitted-aa
.rw-r--r--@ 700k user 31 Oct 20:49 splitted-ab
.rw-r--r--@ 700k user 31 Oct 20:49 splitted-ac
.rw-r--r--@ 700k user 31 Oct 20:49 splitted-ad
.rw-r--r--@ 700k user 31 Oct 20:49 splitted-ae
.rw-r--r--@ 700k user 31 Oct 20:49 splitted-af
.rw-r--r--@ 700k user 31 Oct 20:49 splitted-ag
.rw-r--r--@ 700k user 31 Oct 20:49 splitted-ah
.rw-r--r--@ 700k user 31 Oct 20:49 splitted-ai
.rw-r--r--@ 700k user 31 Oct 20:49 splitted-aj

今回はaa~ajが付けられていますね(xは指定しなかった時の接頭辞になるようです)。

通し番号を数字に変更する

先ほどまでの例ではxaaのように通し番号が数字ではなくアルファベットになっていました。これを数字にしたい場合は-dオプションを利用することで対応できます。例えば以下を実行すると00から99までの数字で通し番号をつけることができます。

split -l 100000 -d original.txt

# 結果
.rw-r--r--@ 6.9M user 31 Oct 20:33 original.txt
.rw-r--r--@ 589k user 31 Oct 21:11 x00
.rw-r--r--@ 700k user 31 Oct 21:11 x01
.rw-r--r--@ 700k user 31 Oct 21:11 x02
.rw-r--r--@ 700k user 31 Oct 21:11 x03
.rw-r--r--@ 700k user 31 Oct 21:11 x04
.rw-r--r--@ 700k user 31 Oct 21:11 x05
.rw-r--r--@ 700k user 31 Oct 21:11 x06
.rw-r--r--@ 700k user 31 Oct 21:11 x07
.rw-r--r--@ 700k user 31 Oct 21:11 x08
.rw-r--r--@ 700k user 31 Oct 21:11 x09

分割最大数について

先ほどデフォルトの分割設定で実行すると以下のエラーが発生するとお伝えしました。これは接尾辞のながさ(xaax以外の部分)がデフォルトで2であり、その場合最大生成できるのあ26*26=676ファイルとなります(アルファベットの組み合わせ)。1000行ずつで区切った場合1000ファイルへの分割が必要ですがながさ2だと対応しきれずエラーが出ていました。

split: too many files

そのような背景から、接尾辞のながさを3以上に変更すればデフォルトの1000行単位でも分割できそうです。そのような場合に利用できるのが-aオプションになります。-aオプションを利用すると接尾辞のながさを指定できます。今回は3で指定すれば実現できそうなので試してみます。

split -l 1000 -a 3 original.txt splitted

こちらを実行すると先ほど発生していたエラーは発生しなくなりました。ファイル一覧を見ると以下のようになっています。

.rw-r--r--@ 6.9M user 31 Oct 20:33 original.txt
.rw-r--r--@ 3.9k user 31 Oct 21:00 splitted-xaaa
.rw-r--r--@ 5.0k user 31 Oct 21:00 splitted-xaab
.rw-r--r--@ 5.0k user 31 Oct 21:00 splitted-xaac
.rw-r--r--@ 5.0k user 31 Oct 21:00 splitted-xaad
.rw-r--r--@ 5.0k user 31 Oct 21:00 splitted-xaae
.rw-r--r--@ 5.0k user 31 Oct 21:00 splitted-xaaf
...
.rw-r--r--@ 7.0k user 31 Oct 21:00 splitted-xbmg
.rw-r--r--@ 7.0k user 31 Oct 21:00 splitted-xbmh
.rw-r--r--@ 7.0k user 31 Oct 21:00 splitted-xbmi
.rw-r--r--@ 7.0k user 31 Oct 21:00 splitted-xbmj
.rw-r--r--@ 7.0k user 31 Oct 21:00 splitted-xbmk
.rw-r--r--@ 7.0k user 31 Oct 21:00 splitted-xbml

aaaからbmlになっており、組み合わせ数を計算するとピッタリ1000になります。

最大バイト数を指定したファイル分割

ここまでの分割は一ファイルあたりの行数に着目して分割していましたが、場合によっては最大容量を指定して分割したいこともあるかと思います。そのような場合に-bオプションが利用でき、最大バイト数を指定して分割させることができます。例えば1000バイトごとに分割させてみます。何ファイルに分割されるか計算するのが面倒だったので-aオプションで余裕を見て5に指定しています。

split -b 1000 -a 5 original.txt splitted-

こちらを実行すると以下のような結果になりました。結果を見ると最後のファイル以外は1000バイトずつで区切られ、最後のファイルだけ残りの890バイトであると確認できました。

.rw-r--r--@ 6.9M user 31 Oct 20:33 original.txt
.rw-r--r--@ 1.0k user 31 Oct 21:08 splitted-aaaaa
.rw-r--r--@ 1.0k user 31 Oct 21:08 splitted-aaaab
.rw-r--r--@ 1.0k user 31 Oct 21:08 splitted-aaaac
.rw-r--r--@ 1.0k user 31 Oct 21:08 splitted-aaaad
.rw-r--r--@ 1.0k user 31 Oct 21:08 splitted-aaaae
.rw-r--r--@ 1.0k user 31 Oct 21:08 splitted-aaaaf
.rw-r--r--@ 1.0k user 31 Oct 21:08 splitted-aaaag
.rw-r--r--@ 1.0k user 31 Oct 21:08 splitted-aaaah
...
.rw-r--r--@ 1.0k user 31 Oct 21:08 splitted-aakes
.rw-r--r--@ 1.0k user 31 Oct 21:08 splitted-aaket
.rw-r--r--@ 1.0k user 31 Oct 21:08 splitted-aakeu
.rw-r--r--@ 1.0k user 31 Oct 21:08 splitted-aakev
.rw-r--r--@ 1.0k user 31 Oct 21:08 splitted-aakew
.rw-r--r--@ 1.0k user 31 Oct 21:08 splitted-aakex
.rw-r--r--@  890 user 31 Oct 21:08 splitted-aakey

なお、分割数は6889でした(ll | grep splitted | wc -lで確認)。

まとめ

今回はsplitコマンドを紹介しました。頻繁に利用するようなコマンドではないかと思いますが、ファイルを分割したい場合にぜひご利用ください。

Discussion