How can you check for STDIN input in a Ruby script?
This is something that's done in Linux a lot:
#!/usr/bin/env ruby
str = (STDIN.tty?) ? 'not reading from stdin' : $stdin.read
puts str
>> $ ruby test.rb
>> not reading from stdin
>> $ echo "reading from stdin" | ruby test.rb
>> reading from stdin
Detecting stdin content in Ruby
Look at $stdin.tty?
ruby cat.rb
# $stdin.tty? -> true
echo hello | ruby cat.rb
# $stdin.tty? -> false
How can I get piped data with arguments on Ruby2.4
It seems that in ruby you want to read from ARGF. It handles files passed as filenames or piped to your program.
What does #tty? on STDIN mean / do in ruby?
Seems like http://www.jstorimer.com/blogs/workingwithcode/7766125-writing-ruby-scripts-that-respect-pipelines supplies the most concise description of what #tty?
does:
Ruby's IO#isatty method (aliased as IO#tty?) will tell you whether or not the IO in question is attached to a terminal. Calling it on $stdout, for instance, when it's being piped will return false.
Here is some relevant info that you may find useful:
- Detecting stdin content in Ruby
- How can you check for STDIN input in a Ruby script?
- https://stackoverflow.com/a/273605
- https://gist.github.com/timuruski/6072363
Background meaning via What do pty and tty mean?:
In UNIX, /dev/tty* is any device that acts like a "teletype", ie, terminal. (Called teletype because that's what we had for terminals in those benighted days.)
In the spirit of the question, here's an example of writing to /dev/tty
from http://zetcode.com/lang/rubytutorial/io/:
#!/usr/bin/ruby
fd = IO.sysopen "/dev/tty", "w"
ios = IO.new(fd, "w")
ios.puts "ZetCode"
ios.close
Piping stdin to ruby script via `myapp | myscript.rb`
Try just plain gets
, without the $stdin
. If that doesn't work, you might have to examine the output of myapp.exe
for non-printable characters with another ruby script, using IO.popen
.
Ruby STDIN, blocking vs not blocking
So the short answer is yes, you are getting an EOF from the pipe. Because the way echo works is that it's going to open the pipe for writing, write to it, then close (i.e. send EOF). Then a new call to echo will open it back up, read to it, and then close.
If you had instead used a program that printed lines of a file after a 3 second sleep, you would see that your application would perform blocking waits until that one exits (at which point the never-ending EOFs would return).
# slow_write.rb
ARGF.each do |line|
puts line
STDOUT.flush
sleep 3
end
I should note that this behavior is not specific to Ruby. The C stdlio library has the exact same behavior and since most languages use C primitives as their basis they have the same behavior as well.
Related Topics
How to Install a Gem or Update Rubygems If It Fails With a Permissions Error
Getting Output of System() Calls in Ruby
Difference Between Include and Extend in Ruby
How to "Pretty" Format Json Output in Ruby on Rails
How to Create a Deep Copy of an Object in Ruby
Continuously Read from Stdout of External Process in Ruby
Incompatible Character Encodings: Ascii-8Bit and Utf-8
Using Net::Http.Get For an Https Url
How to Configure Webrick to Use Ssl in Rails
Regular Expressions With Validations in Ror 4
How to Reload the Current Page in Ruby on Rails
Difference Between Rake Db:Migrate Db:Reset and Db:Schema:Load
What Is the Best Method of Handling Currency/Money
Best Practices With Stdin in Ruby
Converting a Nested Hash into a Flat Hash
Why Does Ruby Have Both Private and Protected Methods
Mixing Keyword With Regular Arguments in Ruby
Is There a Reason That We Cannot Iterate on "Reverse Range" in Ruby