LoginSignup
0
0

More than 1 year has passed since last update.

pbcopyコマンドはデータ内容によってコピペできないことがあるっぽい

Posted at

きっかけ

$ 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
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0