Reputation: 342
How do I get the line count of a file into a variable in Ruby using the Unix command wc for speed for very large files whilst making sure that it's safe from command injection using either open3, system or something similar to achieve the same output as `wc -l < "#{file_path}".to_i`
Upvotes: 0
Views: 92
Reputation: 969
If you prefer to use native shell command and the only thing you want is to escape file_path, there is a Shellwords class in the standard library.
It's very easy to use it in your task:
require 'shellwords'
`wc -l < #{Shellwords.escape(file_path)}`.to_i
Upvotes: 1
Reputation: 434755
Probably the easiest is to use Open3::capture2
:
output, status = Open3::capture2('wc', '-l', file_path)
Then you can check status
and deal with errors as needed and since output
should be something like " 2342 file_path\n"
, you can get the count with a simple #to_i
call:
line_count = output.to_i
If you don't care about error handling (which would never happen in real life):
line_count = Open3::capture2('wc', '-l', file_path).first.to_i
No shell will be involved, no command injection issues.
However, this assumes that the first wc
in your PATH
is the wc
you want to use so you might want to be more specific:
# Or ensure that your PATH environment variable is sensible.
output, status = Open3::capture2('/usr/bin/wc', '-l', file_path)
This also assumes that you want the users to be able to read any file that your process can; if that's not the case then you'd need to blacklist/whitelist file_path
to make sure it is something that they're supposed to be able to read.
Of course, if you're going to all this trouble you might as well open the file and count the lines yourself with a couple lines of Ruby:
# Or some variation on this and a `rescue` to catch exceptions.
line_count = File.open('Gemfile') { |fp| fp.each_line.count }
Upvotes: 1