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.
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
Related
Sort of an odd question, but: how would one go about creating a wrapper shell script that can be used in the #! line in other scripts.
wrap.sh
#!/bin/bash
set -e
echo "wrapper!"
exec ruby "$#"
test.rb
#!/usr/bin/env wrap.sh
puts RUBY_VERSION
puts "the ducks come from the trucks"
wrap.sh is in the path, and test.rb is marked as executable.
Now I do:
./test.rb
wrapper!
ruby: no Ruby script found in input (LoadError)
The goal is to execute the ruby script via the wrapper (The ruby version can be either local or comes from a traveling ruby install that is shipped along with the app).
As far as I can tell ruby is invoked, it's just unhappy with the #! in the test.rb and refuses to run the script. I cannot remove the #! because that's how the script is executed in the first place.
Any workarounds for this?
So, I cannot use rbenv/rvm/etc. There is more logic in the wrapper than this, but this is the gist of it.
Looks to me like the arguments are not being passed to Ruby in "$#". I don't think the bang-hash line is the problem.
I don't see anything in your script which actually passes the contents of test.rb to wrapper.sh, which is the bigger issue.
Perhaps the real problem can be solved by some other means? For example, is the problem you're trying to solve to run arbitrary commands prior to the invocation of any Ruby script from the command line? Perhaps it can be approached that way...
It looks like Ruby just checks that the hash-bang line contains "ruby": https://github.com/ruby/ruby/blob/v2_2_2/ruby.c#L1580 So basically having ruby somewhere in the #! line is all it takes.
I have a Ruby file, and I run it as ruby file.rb "parameters". I prefer to run it as regtask parameters without having to include ruby and the filename every time. I want it to be on the same level as ls. How would I accomplish this?
Edit your file, make sure this is the first line, so your system knows how to execute your file:
#!/usr/bin/env ruby
Next, change the file's permissions to make it executable:
chmod a+x file.rb
And finally, rename it and move it somewhere where it will be executed without having to write its full path:
mkdir -p ~/bin
mv file.rb ~/bin/regtask
(Most systems will automatically add ~/bin to PATH if it exists; if not, you will have to add it to PATH yourself in your startup files.)
This should help.. Please let me know if you run into any issues.
http://commandercoriander.net/blog/2013/02/16/making-a-ruby-script-executable/
Making a Ruby Script Executable
It's common knowledge in the *nix community, but for many new developers turning a Ruby script into an executable command line program is akin to magic. While there are other references on the internet, for the post here, I will briefly explain how to go from running a Ruby script by invoking Ruby directly, to running the script by its name alone.
We will start by assuming we have a simple Ruby script which prints "hello" on the command line. Our script's name will be greeter.rb. The file holds one line of Ruby code:
puts "Hello!"`
To run the script, we must type ruby greeter.rb. Wouldn't it be nice to just type greeter instead and still get the script to run? Yes, it would.
First, we need to tell Bash what to do with our file since we won't be passing the script to Ruby directly. To do that, we add the following to the very top of our script:
#!/usr/bin/env ruby
puts "Hello!"
The first line is a Bash directive and basically tells Bash what program to run our file with by asking for the current configured version of Ruby as specified by the env command. For more on how env works, try typing man env into the command line.
Second, we need to make our script executable, which requires changing the file permissions. If the concept of file permissions is new, read about it here. Bascially, files have three types of permissions. They can be read, written, and executed. Most files typically start out as only having read and write access. Since we want to execute our script, we're going to have to grant it execute permissions.
Doing that is just a simple Bash command. On the command line, navigate to the directory holding the greeter.rb file. Now, to check the permissions, run:
ls -l greeter.rb
The output will look something like this:
-rw-r--r-- 1 username staff 13 Feb 16 21:10 greeter.rb
Your own username will show up in the place of username, and the creation date will naturally be different, but otherwise the output will be almost identical. The first part of the line is the revelant part. The letters r and w specify read and write permissions.
We're going to add execute permissions which will appear as an x in that line. To add execute permissions, run the following command.
chmod 755 greeter.rb
Now, if you check the file permissions again with ls -l greeter.rb, the output should be a little different.
-rwxr-xr-x 1 username staff 13 Feb 16 21:20 greeter.rb
The presence of x indicates that the file can be run directly without calling Ruby first. The following command should get our file to say "hello."
./greeter.rb
Almost there. Now, we just need to get rid of the prefix ./, which tells Bash where to look for greeter.rb, i.e., in the current directory. Before we complete this last step, though, let's rename our file to just greeter.
mv greeter.rb greeter
Now, for the last step. Everytime we call a Bash program, e.g., ls, chmod, mv, etc., Bash searches through a predefined list of folders looking for those programs. This is called the path. To see what the path is set to on your computer, try:
echo "$PATH"
The output should be a long string of various system-critical folders. We need to put our application into one of these folders. Traditionally, it's best to leave folders like /usr/bin/ and /bin/ alone. Instead, any kind of user additions should be placed in /usr/local/bin/. If that folder doesn't exist, create it with:
mkdir -p /usr/local/bin/
Now, we can either move our greeter into that folder, or leave the application where it is and just create a softlink (or an alias in OS X terms) within the /usr/local/bin/ folder. To create an alias, we'll use the ln command. From the directory where greeter lives, type:
ln -s $PWD/greeter /usr/local/bin/
Note that the $PWD variable will expand to an absolute path to our greeter script. Now, we're done and we can simply type greeter to invoke our Ruby script!
As a footnote, if any of the above Bash commands seem confusing, trying looking up their man page by typing man <command>.
I was trying to figure out how to work the command line switch -r.
My understanding is that the code is typed out as follows:
ruby -r*nameOfRequired*
I am finding that this is not the case. When I type out the above and press enter, the terminal expects an "end of input syntax" and does not continue.
What am I missing? Does there need to be a space in between the switch and the name of the required file?
Please and thank you!
EDIT:
I am currently reading "The Well Grounded Rubyist" by David A. Black, and I came up with this question while reading the section on command line switches.
Having said that, I created a "test.rb" file, containing:
puts Date.today
Then, in the terminal, I typed out:
ruby -r date
I thought this would 'require' the date module, and then enable me to run the "test.rb" file, using ruby test.rb (given that I am in the correct directory).
Instead, the terminal cursor moves to a newline, expecting more input. Let me know if I need to clarify anything else. Thanks!
If you just type ruby -rmodule, then Ruby will load the module and wait for you to type the main program that requires that module.
If you just want to run the module and do nothing else, you can do do rubyfull-path-to-module without the -r, or ruby -rmodule -e exit, or ruby -rmodule </dev/null, or similar.
In general, the ruby command does not record any state from one run to the next, so you need to tell it every thing that it needs to know whenever you run it.
Whenever you run it, you need to tell it the main program to run or else it will expect you to type that program on the standard input. The -r does not specify the main program.
Try this:
ruby -rdate test.rb
According to ruby -h:
-rlibrary require the library, before executing your script
Without giving your script file path, it read the script from stdin.
Try following (You can omit script file path when you give -e command):
ruby -r**nameOfRequired** -e ""
I am doing a series of tutorials on how to code in Ruby. I want to read a .txt file using this formula:
filename = ARGV.first
prompt = "> "
txt = File.open(filename)
puts "Here's your file: #{filename}"
puts txt.read()
puts "I'll also ask you to type it again:"
print prompt
file_again = STDIN.gets.chomp()
txt_again = File.open(file_again)
puts txt_again.read()
The text file reads:
This is stuff I typed into a file. It is really cool stuff.
Lots and lots of fun to have in here.
The name for the text file is ex15_sample.txt. I tried with the above formula, and nothing seems to work. I have a hard understanding how to use both ARGV and STDIN.gets.chomp.
What should I do? I ask that you use the formula above; this stuff is a little confusing, so for now, just use the formula above.
The script works. You're not explaining how you're trying to run the script or what errors you're seeing, so it's a bit hard to help you.
If you have a text file named ex15_sample.txt in the same directory as your script (let's call it script.rb), and if you have Ruby set up properly, then if you run it with
$ ruby script.rb ex15_sample.txt
everything should work fine.
If you're trying to change the first line to always use ex15_sample.txt, be sure to put it in quotes:
filename = "ex15_sample.txt" # Without the quotes, you'll get an error.
Again, it's hard to help you without knowing exactly how you're running the script or what errors you're getting.
Update: I seems your issue is that you aren't clear on how to run a Ruby script. The simplest way is to, at your system's command prompt, type ruby then a space, then the name of the file with a Ruby script in it. If your script is in a file named script.rb, you would type ruby script.rb. That won't work if your script is in a file with a different name. If the script is in a file named read-a-file.rb, then you need to type ruby read-a-file.rb.
This particular script wants a command line argument after the file name. If the text file you want to read is in a file named ex15_sample.txt, then you need to type that after the script name. In the previous example, the command would become ruby read-a-file.rb ex15_sample.txt. That will only work if the files are in the same directory (a.k.a. folder).
This isn't working in ruby and I don't understand why?
#!/usr/bin/env ruby
exec "sort data.txt > data.sort"
data.txt is a comma sepparated file. Anyway.. If I try to execute that line in the shell it works without a problem.
When I try to run this script from my script, I get an empty file.
This isn't really an answer, but I wanted to share that your original usage of exec is actually working for me. This was how I set it up.
data.txt
"1,2,3,4,5,6,7,8"
sort.rb (I don't know what your sort did so I am just writing the same data out)
File.open(ARGV[0]){|f| puts f.read}
irb session
irb(main):001:0> exec "sort data.txt > data.sort"
When I ran this in irb, I did get a data.sort output file and it contained "1,2,3,4,5,6,7,8" as expected. I can run the same exec line through irb or from another ruby file, and I get the output file with data each time.
I am running Ruby 1.8.6 on a 32bit Windows XP system.
Have you tried
%x(sort data.txt > data.sort)