Parsing unix filenames from STDIN

How can I parse filenames read from STDIN via the standard Unix parsing
rules (without duplicating said rules)? All of the following would be
parsed as coherent file names:

file.txt
my\ file.txt
“my file.txt”

A nice addition would be that *.txt would use Bash expansion to find the
appropriate files.

ARGF isn’t working for me because it tries to actually read the files in
(and some of the arguments in STDIN are commands, not filenames).

David

On Sat, Aug 25, 2012 at 7:57 AM, David J. [email protected] wrote:

ARGF isn’t working for me because it tries to actually read the files in (and
some of the arguments in STDIN are commands, not filenames).

try ARGV, eg,

$ echo p ARGV > test.rb

$ ruby test.rb file.txt my\ file.txt “my file.txt”
[“file.txt”, “my file.txt”, “my file.txt”]

best regards -botp

On Sat, Aug 25, 2012 at 12:57 AM, David J. [email protected] wrote:

How can I parse filenames read from STDIN via the standard Unix parsing rules
(without duplicating said rules)? All of the following would be parsed as coherent
file names:

file.txt
my\ file.txt
“my file.txt”

A nice addition would be that *.txt would use Bash expansion to find the
appropriate files.

Use Shellwords to handle shell escaped strings and Dir[] to expand
wildcards:

require ‘shellwords’
while line = STDIN.gets
filename = Shellwords.shellwords(line).join(‘’)
p filename

expand wildcards

p Dir[filename]
end

Regards,
Sean

On Mon, Aug 27, 2012 at 10:51 AM, Robert K.
[email protected] wrote:

Two additional cents:

  1. I’d rather use $stdin instead of STDIN, see here for reasoning:

Good point. I agree.

expand wildcards

p Dir[filename]
end

Advantage is also that the scope of “line” is limited to the block
reducing potential for errors.

Another good point.

Btw, Sean, are you sure David will join all the shellwords?

No, I wrote my response after quickly reading his examples, not
by reading carefully to the end of his post.

Hat trick! I agree with all your points :slight_smile:

Kind regards

robert


remember.guy do |as, often| as.you_can - without end

Indeed. All the best,
Sean

On Sat, Aug 25, 2012 at 11:51 AM, Sean O’Halpin [email protected]
wrote:

require ‘shellwords’
while line = STDIN.gets
filename = Shellwords.shellwords(line).join(‘’)
p filename

expand wildcards

p Dir[filename]
end

Two additional cents:

  1. I’d rather use $stdin instead of STDIN, see here for reasoning:
    What is the difference between STDIN and $stdin in Ruby? - Stack Overflow

  2. One can as well use the usual iteration for reading lines from files.

=>

require ‘shellwords’

$stdin.each_line do |line|
filename = Shellwords.shellwords(line).join(‘’)
p filename

expand wildcards

p Dir[filename]
end

Advantage is also that the scope of “line” is limited to the block
reducing potential for errors.

Btw, Sean, are you sure David will join all the shellwords? I am
asking since he said there were commands as well and he basically
wants to parse in the same way the shell does. So:

irb(main):006:0> [‘my\ file.txt’, ‘“my file.txt”’, ‘ls foo\
bar.txt’].each {|s| printf “%p → %p\n”, s, Shellwords.shellwords(s)}
“my\ file.txt” → [“my file.txt”]
“"my file.txt"” → [“my file.txt”]
“ls foo\ bar.txt” → [“ls”, “foo bar.txt”]
=> [“my\ file.txt”, “"my file.txt"”, “ls foo\ bar.txt”]

Kind regards

robert

Sorry for the delay. Thanks for the pointer to Shellwords and to
iteration, guys!

David

FYI I ended up using the following (turns out I didn’t need bash
expansion because I’ll always get that from the previous tool in the
pipeline):

if $stdin.tty?

… do something

else
files = $stdin.each_line.reduce([]) do |list, line|
list.concat(Shellwords.split(line))
end

… do something with files

end