30

I'm trying to pass the array contained in a global variable I've created into my clipboard on my mac.

It is very long so I don't want to highlight, copy & paste on my console.

I want to use embedded unix code, specificially the pbcopy function for the mac laptop console that allows me to pass text into my computers clipboard, ready to paste.

Were I to do this with a file-save, I'd do something like this (in ruby):

stringdata = <<blah blah blah process, lets say it failed and the progress data is stored in this variable so we can skip forward to where the script screwed up in a process when we start up and handle the error instance(s)>>
File.open("temp.txt"){|f| f.write(stringdata)}
`cat temp.txt | pbcopy`

But could I possibly do this without creating a temporary file?

I'm sure this is possible. All things in text are possible. Thanks in advance for the solution

boulder_ruby
  • 38,457
  • 9
  • 79
  • 100

3 Answers3

42

You can just echo it instead if there are no newline characters in the string; otherwise, use the IO class.

Using echo:

system "echo #{stringdata} | pbcopy"

OR

`echo #{stringdata} | pbcopy`

Ruby will then just rip the text from memory, inject it into the shell command which opens a pipe between the echo and pbcopy processes.

Using the IO class:

If you want to do it the Ruby way, we simply create a pipe with pbcopy using the IO class. This creates a shared files between the processes which we write to, and pbcopy will read from.

IO.popen("pbcopy", "w") { |pipe| pipe.puts "Hello world!" }

Wen
  • 1,230
  • 1
  • 14
  • 28
ianks
  • 1,708
  • 19
  • 15
  • wouldn't I have to put the text in quotations of some kind?? – boulder_ruby Dec 03 '14 at 14:44
  • No, `echo` doesn't require that. Try this code in IRB: `echo #{"helllo this is my test"} | pbcopy` ... You will then be able to paste `hello this is my test` from your clipboard. – ianks Dec 03 '14 at 18:09
  • 3
    Is this supposed to be able to run in `irb` ? I get this response: `Errno::ENOENT: No such file or directory - pbcopy` ` – Pak May 16 '16 at 09:50
  • 3
    This does not appear to run in `irb`. Here's what happened when I did that. `$ irb 2.2.2 :001 > echo #{"helllo this is my test"} | pbcopy NameError: undefined local variable or method 'echo' for main:Object` – bwest87 Jul 20 '16 at 18:25
  • 2
    Try using `IO.popen("pbcopy", "w") { |pipe| pipe.puts "Hello world!" }` instead. – ianks Mar 14 '17 at 19:56
  • 1
    Note that `pbcopy` only exists in OS X. On Linux, you can do something like this: https://coderwall.com/p/oaaqwq/pbcopy-on-ubuntu-linux – wbharding Jul 17 '18 at 20:31
17

Here's a simple one-line method you can paste into your IRB console:

def pbcopy(arg); IO.popen('pbcopy', 'w') { |io| io.puts arg }; end

Once it's defined you can simply do

pbcopy stringdata

or copy the result of the last command with

pbcopy _

Of course, you can also put the method definition in an initializer or something, such as .irbrc or .pryrc if you use pry. Here's a prettier and slightly more intelligent version:

def pbcopy(arg)
  out = arg.is_a?(String) ? arg : arg.inspect
  IO.popen('pbcopy', 'w') { |io| io.puts out }
  puts out
  true
end
linesarefuzzy
  • 1,890
  • 17
  • 17
9

You can use my clipboard gem for a Ruby-API to the system clipboard (which is also platform independet, on macOS it will use the same pbcopy utility under the hood), so that you can use it from IRB:

require 'clipboard'
Clipboard.copy(stringdata);p

Usually, the copy method returns the string which was copied. This the reason for the ;p bit: It is a trick to return nil so that the console would not display the actual string data.

J-_-L
  • 9,079
  • 2
  • 40
  • 37