1

I have a ruby program that accepts files as input. I am trying to test that this functionality works by piping a file into the program by entering

cat file1.txt | ./app.rb

However, when I do this I get -bash: ./app.rb: Permission denied I have tried using sudo cat file1.txt | ./app.rb which prompts me for my password and then it appears nothing happens.

This works fine when I instead type ruby app.rb file1.txt

Does anyone have any tips for how to get this to work?

As pointed out in the comments, I need to be able to read a file path from stdin AND pass them as parameters:

In my code I have this:

def input
    if ARGV.length.positive?
      ARGV
    else
      gets.chomp.split(' ')
    end
  end

I expect input to return an array of file paths.

Emily Kingan
  • 183
  • 1
  • 7
  • Reading from a file and from [stdin](https://en.wikipedia.org/wiki/Standard_streams) are two different things. – Cyrus Sep 21 '19 at 16:51
  • 1
    This might help: [Best practices with STDIN in Ruby?](https://stackoverflow.com/q/273262/3776858) – Cyrus Sep 21 '19 at 16:55

1 Answers1

2

As mentioned in the comments above, sending the contents of a file as STDIN to a program and passing the filename as a parameter are two very different things.

I cannot say which, if either, is "right" or "wrong" without knowing more context of what it is you're actually trying to achieve, but it's important to recognise the difference.


Now, the actual cause of the error here is that you're trying to execute the ruby file directly. You can fix this by running ruby on the filename instead:

cat file1.txt | ruby app.rb

It is possible to execute the file without writing ruby, but you must first make it executable:

chmod +x app.rb

And also write a Shebang at the top of the file, to specify that it should be executed as a ruby script, not a bash script (which is the default):

#!/usr/bin/env ruby
Tom Lord
  • 27,404
  • 4
  • 50
  • 77
  • If you type `ls -l app.rb`, you should see something like this: `-rw-r--r--`. This is the unix [file permissions](https://www.tutorialspoint.com/unix/unix-file-permission.htm). See the link for more detail... But since there's no `x` in that list, you don't have permission to e**x**ecute the file. Running `chmod +x` adds execution permission. – Tom Lord Sep 21 '19 at 17:15
  • I actually need to be able to do both, send the file path as stdin and as a parameter. I will elaborate more in my question. – Emily Kingan Sep 21 '19 at 17:46
  • OK.. I think what you're looking for is actually `echo file1.txt`, not `cat file1.txt`. You want to pass the file **name**, not the file **contents**. – Tom Lord Sep 21 '19 at 17:49
  • Anyway, I think my answer is still correct. Does this solve your problem? – Tom Lord Sep 21 '19 at 17:50
  • Thank you for the response. `cat file1.txt | ruby app.rb` worked like a charm. The Shebang didn't seem to help. I placed it at the top of `app.rb`. I am using MacOs if that helps. – Emily Kingan Sep 21 '19 at 17:50
  • I basically need the program to accept a list of one or more file paths (e.g. ./app.rb file1.txt file2.txt ...). and also accepts input on stdin (e.g. cat file1.txt | ./app.rb). @tomlord – Emily Kingan Sep 21 '19 at 17:53
  • @EmilyKingan My point is you "expect `input` to return an array of file paths", but by running `cat file1.txt`, you are not sending the file *path* via STDIN, you are sending the file *contents* via STDIN. That's why I suggest instead using `echo file1.txt`, to only send the file *path*. – Tom Lord Sep 21 '19 at 17:58