Bashでテスト用に1GiBの大容量ファイル(バイナリ/テキスト)を作成する方法いろいろ

2023-03-27Bash,CentOS,Linux,Mac,Ubuntu

はじめに

アップロード・ダウンロード速度、通信速度を確認するために、サイズの大きなファイルを作成したいときがあります。

よく知られた方法ばかりですが、1GB の大容量のファイルを作成する方法を紹介します。

検証環境

$ uname -moi
aarch64 aarch64 GNU/Linux

$ head -n 2 /etc/os-release
NAME="Ubuntu"
VERSION="21.04 (Hirsute Hippo)"

$ bash -version | head -n 1
GNU bash, バージョン 5.1.4(1)-release (aarch64-unknown-linux-gnu)

NULL 文字(0x00)で埋められた「バイナリファイル」を作成

最もかんたんかつ高速なのは、 dd コマンドを使って NULL 文字(0x00)で埋められたバイナリファイルを作成する方法 です。

$ dd if=/dev/zero of=1Gi bs=1024 count=$((1024**2))
1048576+0 レコード入力
1048576+0 レコード出力
1073741824 bytes (1.1 GB, 1.0 GiB) copied, 2.45573 s, 437 MB/s

bs でブロックサイズ 1024bytes を指定しています。
このブロックを、count の回数分、つまり 1024**2 回書き込みます。

合計サイズは 1024**3 = 1073741824 となります。

作成されたファイルの容量を確認してみます。

$ ls -l 1Gi
-rw-r--r-- 1 root root 1073741824  3月  8 08:43 1Gi

$ stat 1Gi
  File: 1Gi
  Size: 1073741824   Blocks: 2097160    IO Block: 4096   通常ファイル
Device: 40h/64d Inode: 7086333     Links: 1
Access: (0644/-rw-r--r--)  Uid: (    0/    root)   Gid: (    0/    root)
Access: 2022-03-08 08:43:17.848731009 +0900
Modify: 2022-03-08 08:43:20.304731010 +0900
Change: 2022-03-08 08:43:20.304731010 +0900
 Birth: 2022-03-08 08:43:17.848731009 +0900

サイズは 1024 ** 3 = 1073741824 bytes となりました。

ランダムデータで埋められた「バイナリファイル」を作成

NULL 文字で埋められたファイルですが、
すべての内容が同じ NULL 文字ですので 処理の過程で圧縮が適用されるような仕組み(ファイルシステムやネットワーク通信)では
想定よりも高性能で扱われてしまう可能性があります。

テスト用の巨大ファイルといえどランダムデータのほうが良い場合は、 dd コマンドの引数を少し書き換えてやります。

$ dd if=/dev/urandom of=1Gi-random bs=1024 count=$((1024**2))
1048576+0 レコード入力
1048576+0 レコード出力
1073741824 bytes (1.1 GB, 1.0 GiB) copied, 5.54216 s, 194 MB/s

サイズだけを見ると先程のファイルと同じサイズで違いがわかりません。

$ ls -la 1Gi-random
-rw-r--r-- 1 root root 1073741824  3月  8 08:54 1Gi-random

$ stat 1Gi-random
  File: 1Gi-random
  Size: 1073741824   Blocks: 2097160    IO Block: 4096   通常ファイル
Device: 40h/64d Inode: 7086334     Links: 1
Access: (0644/-rw-r--r--)  Uid: (    0/    root)   Gid: (    0/    root)
Access: 2022-03-08 08:54:07.875765004 +0900
Modify: 2022-03-08 08:54:13.417765007 +0900
Change: 2022-03-08 08:54:13.417765007 +0900
 Birth: 2022-03-08 08:54:07.875765004 +0900

両方のファイルの先頭 8 バイトを確認してみます。

$ od -tx1 -N8 1Gi
0000000 00 00 00 00 00 00 00 00
0000010

$ od -tx1 -N8 1Gi-random
0000000 74 06 2c fe 39 f7 fd 14
0000010

od コマンドで確認すると、

  • 先ほどの if=/dev/zero オプションを指定して作成したファイルはすべての 0 となっています。
  • 対して今回作成した if=/dev/urandom オプションを指定して作成したファイルはランダムな値となっています。

圧縮してみると更に違いがわかります。

$ gzip 1Gi

$ gzip 1Gi-random

$ ls -l
合計 1049772
-rw-r--r-- 1 root root 1073915365  3月  8 08:54 1Gi-random.gz
-rw-r--r-- 1 root root    1042073  3月  8 08:43 1Gi.gz

すべて NULL 文字で詰められたファイルの圧縮済みファイルのサイズは非常に小さいです。
対して、 if=/dev/urandom オプションを指定したファイルは圧縮率が低く、サイズがあまり変わっていません。

ランダムデータで埋められた「テキストファイル」を作成

ここまでは バイナリファイル の作成コマンドでしたが、次は テキストファイル の作成方法について紹介します。

/dev/urandom を使うのは同じですが、出力内容をテキストに変換してやります。

$ cat /dev/urandom | base64 | head -c $((1024**3)) > 1Gi.txt

head コマンドに -c オプションを付けて、指定したバイト数だけ抽出しています。

先頭の数行を出力し確認してみます。

$ head 1Gi.txt
h/HyuOkcgalT0Wk796+mpSrG125X7sZWt53JXsy45QUOj0q0u5adxbcRsisX76E+NJr7zvioAbrO
ec0qe2o66dnu31DFY6iTXMLKsLM1UDAmKhE3T7oWIF9iHIWoGXu1WrDjaGvoQuydslqMNfOsJThR
BXLgv5qdiVHc52MkFXe4xKPN1d0rJn+Lpjhwqb1Ev8qS9Fu3nnyrF42avlj08PeJyEBru4bxGyOa
J0EDKbwXQBxwW6tIXu2xttXLlUqnG3YMOkOr4jzJ4M/BesZOmgDk8vm9aFV/TllN1ypdmflC0DoZ
/K32u0UtBCdJ+D1go3pzV0/ZuhNs0n3xRKtUGE4Rrtxt/hG8ooA2nVCcem8sjo8LunrTcoxmaUIM
tEaEx5JPrggmcsJoWPI0gu4CrFDJBGzdYBJr9qqogoQT6QmKSbEUHfNuYAfrQX0TwM6h9R/3YXIh
JyS5oZALa2YfciB04NJgX8ZiJ1Gek0pWJl6BxcrVmUlobJ8LZ4PTazyW1b+Bc1Id1bJX8E+gSOo1
AMn9coZviqlkGu8O9kq+0gj1TqXtRxUf57QZ0ygj7g6+6qnV/0+OklyzfY1FIK5nx/xTt7du1SdQ
pYSBw7GWhBL6F3XzLmU+AlcnLBblsGHSuRiwb8lZsSP5RZ8dFhgnNbnUZSoaocj3lKK9Qk9zDpNM
79NPpjZS2ilJ/bZyUwm8gxpq3hicdbfInMAr0+9oL4vSlsmwYV0exQD9NtVrKFzuKxNDyg6r8sia

テキストファイルとなっています。

ファイルサイズも確認してみます。

$ ls -l
合計 1048576
-rw-r--r-- 1 root root 1073741824  3月  8 09:10 1Gi.txt

$ stat 1Gi.txt
  File: 1Gi.txt
  Size: 1073741824   Blocks: 2097152    IO Block: 4096   通常ファイル
Device: 40h/64d Inode: 7086334     Links: 1
Access: (0644/-rw-r--r--)  Uid: (    0/    root)   Gid: (    0/    root)
Access: 2022-03-08 09:09:59.648677000 +0900
Modify: 2022-03-08 09:10:02.640677002 +0900
Change: 2022-03-08 09:10:02.640677002 +0900
 Birth: 2022-03-08 09:09:59.648677000 +0900

1024**3 = 1073741824 bytes となっています。
サイズは 1GiB となっていますね。

macOS の場合は mkfile コマンドも利用可能

macOS 環境では、 mkfile コマンドを使うこともできます。

$ mkfile 1g hoge
mkfile 1g hoge  0.21s user 4.39s system 93% cpu 4.901 total

$ stat hoge
  File: hoge
  Size: 1073741824      Blocks: 2106144    IO Block: 4096   regular file
Device: 1,15    Inode: 5261319     Links: 1
Access: (0600/-rw-------)  Uid: (  501/genzouw)   Gid: (   20/   staff)
Access: 2022-03-08 09:13:26.269715538 +0900
Modify: 2022-03-08 09:13:31.166168850 +0900
Change: 2022-03-08 09:13:31.166190017 +0900
 Birth: 2022-03-08 09:13:26.269715538 +0900

中身を見ると NULL 文字 で満たされているようなので、 dd コマンドと同じですね。

$ od -tx1 -N8 hoge
0000000 00 00 00 00 00 00 00 00
0000010

ひとこと

巨大なバイナリファイルの作成例は紹介されていることが多いですが、
巨大なテキストファイルの作成例は参考にしていただけるのではないでしょうか?

2023-03-27Bash,CentOS,Linux,Mac,Ubuntu