What's the best way to optionally specify an output file but use stdout by default?
Right now I'm trying:
opts = Trollop::options do
opt :output, "Output File", :default => $stdout
opt :input, "Input File", :default => $stdin
end
But when I try using it, I get:
$ ./test.rb -o temp.txt
Error: file or url for option '-o' cannot be opened: No such file or directory - temp.txt.
Try --help for help.
Obviously I don't want to require the output file to exist prior to running my script.
(Also, is the way I'm specifying the input okay?)
Looking at the code in trollop (specifically parse_io_parameter) I believe that currently, trollop (version 1.16.2) assumes any IO type argument (as in the question) is assumed to be for input.
The workaround is as follows.
Use a String to specify the output file in trollop:
opts = Trollop::options do
opt :input, "Input File", :default => $stdin
opt :output, "Output File", :default => "<stdout>"
end
Create an output object (out) based on the parsed argument:
out = if opts[:output] =~ /^<?stdout>?$/i
$stdout
else
fd = IO.sysopen(opts[:output], "w")
a = IO.new(fd, "w")
end
Then you can use it like this:
out.puts("this text gets written to output")
Related
I have the following code:
#!/usr/bin/env ruby
require 'yaml'
require 'json'
require 'getoptlong'
DEFAULT_CONF_FILE = 'conf.yaml'
opts = GetoptLong.new(
[ '--asn', '-a', GetoptLong::OPTIONAL_ARGUMENT ],
[ '--modify', '-m', GetoptLong::OPTIONAL_ARGUMENT ]
)
config_file = ARGV[0]
if config_file.to_s.empty?
config_file = DEFAULT_CONF_FILE
end
opts.each do |opt, arg|
case opt
when '--asn'
write_asn_database(arg,config_file)
when '--modify'
generate_modify_conf_file(arg,config_file)
end
end
This code generates some json files according to the given YAML configuration file. And what I am trying to do is:
If in the command line is given a conf file, the program will use that given file;
If not, it will use the default file.
Something like:
Example 1 (with a conf file):
$ ./my_script.rb new_conf_file.yaml -a
Example 2 (without conf file):
$ ./my_script.rb -a
The first example works, the second example gives me the following error:
No such file or directory # rb_sysopen - -a (Errno::ENOENT)
And it makes sense because the program assumes that the option -a is a file.
I'm new to Ruby and I never used the command line to run scripts.
OK, I would post it here. Please do not do this, since it’s just ugly:
config_file = ARGV[0]
unless File.exist?(config_file)
config_file = DEFAULT_CONF_FILE
end
From the very first paragraph of GetoptLong documentation:
The empty option -- (two minus symbols) is used to end option processing. This can be particularly important if options have optional arguments.
Use your code by calling a script as:
# ⇓⇓⇓⇓⇓⇓⇓⇓⇓⇓⇓⇓⇓⇓⇓⇓⇓⇓⇓⇓⇓
./my_script.rb -a -- new_conf_file.yaml
Also, one should put the opts reading part before dealing with ARGV explicitly.
And no, with GetoptLong it is impossible to parse the command line you provided properly.
I'm trying to read the content of a file (myfile.txt) through ARGV in Ruby. Here is my code:
filename = ARGV.first
puts "Here's your file #{filename}:"
print txt.read
What I have to do to pass the name of the file to ARGV?
Solution
With a ruby script called read_file.rb :
# read_file.rb
# example :
# ruby read_file.rb some_file.txt
filename = ARGV.first
puts "Here's your file #{filename}:"
print File.read(filename)
You can call :
ruby read_file.rb myfile.txt
Your code
print txt.read
txt isn't defined. If you meant filename, filename is a String which contains a filename. It's not a File object, so you cannot call filename.read directly.
Best use
ARGF.read
Notice the spelling with an ...F
ARGF is a stream of either all files named in the arguments, or standard input if no file has been named. This is best practice for scripts and allows your program to be used with a unix pipe.
cat filename | ruby script.rb
ruby script.rb filename
Will both work and do the same if you use ARGF.
Try the following.
file = ARGV.first
file_name_with_extn = File.basename file # => "abc.mp4"
file_extn = File.extname file # => ".mp4"
file_name = File.basename file, extn # => "abc"
file_path = File.dirname file # => "/path/"
Why do i get this error 'ruby: No such file or directory -- Readingfile.rb (LoadError)' when i run my ruby program to read files?
My code:
filename = ARGV.first
txt = open(filename)
puts "Heres your file#{filename}:"
print txt.read
print "TYpe the filename again"
file_again = $stdin.gets.chomp
txt_again = open(file_again)
print txt_again.read
'ruby: No such file or directory -- Readingfile.rb (LoadError)'
Without a stack trace, I can only infer that this error originates from the line txt = open(filename). What's most likely is that the filename (first arg passed into $ ruby file.rb) either does not exist or was unspecified (and therefore nil).
In order to ensure that your program is resilient to different kinds of input, you should check and handle cases where no valid filename is passed. This can be done with File#exist?:
puts "Missing filename" and exit! unless filename = ARGV.first
I have created one ruby script that I want to run with some flags on console say -v flag prints output on console and -o stores output in new file with file name I am taking from console using gets()
My code has following structure:
puts "Enter filename to analyze:\n\n"
filename = gets().chomp
puts "Provide filename to store result in new text file:\n\n"
output = gets().chomp
filesize = File.size(filename)
puts "File size in Bytes:\n#{filesize.to_i}\n"
pagecontent = filesize - 20
puts "\n\nData:\n#{pagecontent}\n\n"
File.open(filename,'r') do |file|
#whole process with few do..end in between that I want to do in 2 different #ways.
#If I provide -v flag on console result of this code should be displayed on console
#and with -o flag it should be stored in file with filename provided on console #stored in output variable declared above
end
end
Use stdlib OptionParser
I just updated my ruby version and now when I run irb in command line, I get this weird:
1.9.2p290 :001 >
every line. Before it was a simple >
How can I get it back again?
You can edit your ~/.irbrc file to change the prompt (command line prefix). See this answer for an example. You could put this in there to start:
IRB.conf[:PROMPT][:CUSTOM] = {:PROMPT_I => ">> "}
IRB.conf[:PROMPT_MODE] = :CUSTOM
IRB.conf[:AUTO_INDENT] = true
.irbrc is a Ruby script that irb runs when it starts up that lets you configure your prompt.
From this article, in your user dir ~/, create the .irbrc file with following:
IRB.conf[:PROMPT][:MY_PROMPT] = { # name of prompt mode
:PROMPT_I => ">", # normal prompt
:PROMPT_S => nil, # prompt for continuated strings
:PROMPT_C => nil, # prompt for continuated statement
:RETURN => "=> %s\n" # format to return value
}
IRB.conf[:PROMPT_MODE] = :MY_PROMPT