きっかけ
$ cat file | pbcopy
$ pbpaste
=> 反応なし。。
対象ファイルは、10MB 程の CSV
ちなみに、対象ファイルをエディタで開いて、Command+c + Command+v
でコピペできる
ちょっと気になったので調べてみた
前提
$ sw_vers
ProductName: Mac OS X
ProductVersion: 10.15.7
BuildVersion: 19H15
pbcopy
のバージョンの調べ方は分からなかった。。
サマリー
- 一定のデータサイズを超えるとコピペできなくなる
- ただ、上記の閾値未満において、データサイズの大小と関係なくコピペできる/できないケースがある
- また、データ内容によって、上記の閾値、コピペ可否は変わる
調査
まずはマニュアルを見てみる
$ man pbcopy
特に気になるものはない
1MB だとどうなるか試してみる
$ dd if=file of=test_1m bs=1024 count=1024
$ cat test_1m | pbcopy
$ pbpaste
=> 反応なし。。
データサイズの閾値があるのだろうか、見てみる
"0kb: ng"
"10kb: ok"
"20kb: ok"
"30kb: ok"
"40kb: ok"
"50kb: ok"
"60kb: ok"
"70kb: ok"
"80kb: ng"
"90kb: ng"
"100kb: ok"
"110kb: ok"
"120kb: ok"
"130kb: ok"
"140kb: ok"
"150kb: ok"
"160kb: ok"
"170kb: ok"
"180kb: ok"
"190kb: ok"
"200kb: ok"
"210kb: ng"
"220kb: ok"
"230kb: ok"
"240kb: ok"
"250kb: ng"
"260kb: ng"
"270kb: ok"
"280kb: ng"
"290kb: ok"
"300kb: ok"
"310kb: ok"
"320kb: ok"
"330kb: ng"
"340kb: ok"
"350kb: ok"
"360kb: ng"
"370kb: ok"
"380kb: ok"
"390kb: ok"
"400kb: ok"
"410kb: ok"
"420kb: ng"
"430kb: ok"
"440kb: ng"
"450kb: ng"
"460kb: ok"
"470kb: ng"
...
"10000kb: ng"
データサイズの大小に関わらず、コピペできる/できないケースがある
また、470KB を境にコピペできなくなっている
ちなみに、複数回試したが、同じ結果となった
今度はデータ内容を変えてみる
具体的には、大量のNULL文字(/dev/zero
)と一文字(a
)
"0kb: ok"
"10000kb: ok"
"20000kb: ok"
"30000kb: ok"
...
"260000kb: ok"
"270000kb: ng"
...
"1000000kb: ng"
データ内容によって、コピペ可否の閾値が異なることが分かる
この結果自体は直感通り
コマンド内部で何が起きているのだろう。。
※ 検証スクリプト
- 前提
- ruby 2.7.4
- rails (6.1.6.1)
初回
def exec_command(cmd)
result = `#{cmd}`
raise RuntimeError if $?.exitstatus == 1
result
end
def make_file(src_file, output_file, file_size)
block_size = 1.kilobytes
exec_command("dd if=#{src_file} of=#{output_file} bs=#{block_size} count=#{file_size/block_size} > /dev/null 2>&1")
end
def check_copy?(file)
exec_command("cat #{file} | pbcopy")
result = exec_command('pbpaste')
result.present?
end
def remove_file(file)
exec_command("rm #{file}")
end
# main
src_file = 'file' # 絶対パス
0.step(10000, 10) do |n|
output_file = "test_#{n}"
file_size = n.kilobytes
make_file(src_file, output_file, file_size)
p "#{n}kb: #{check_copy?(output_file) ? 'ok' : 'ng'}"
remove_file(output_file)
end
次回
基本的には、↑と同じだが、一部内容を変更している
...
def make_file(src_file, output_file, file_size)
block_size = 1.kilobytes
exec_command("dd if=#{src_file} of=#{output_file} bs=#{block_size} count=#{file_size/block_size} > /dev/null 2>&1")
exec_command("echo 'a' >> #{output_file}") # 変更(src_fileが/dev/zeroの場合は出力内容がないので追記)
end
...
# main
src_file = '/dev/zero' # 変更(NULL文字で埋める)
0.step(1000000, 10000) do |n| # 変更(閾値の拡大に伴い、処理時間削減のため間隔を広げる)
output_file = "test_#{n}"
file_size = n.kilobytes
make_file(src_file, output_file, file_size)
p "#{n}kb: #{check_copy?(output_file) ? 'ok' : 'ng'}"
remove_file(output_file)
end