# Running a shell command from ruby

**URL:** <https://www.ruby-forum.com/t/running-a-shell-command-from-ruby/190979>\
**Category:** Ruby\
**Created:** [July 1, 2010, 9:53pm UTC](https://www.ruby-forum.com/t/running-a-shell-command-from-ruby/190979 "2010-07-01T21:53:46Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![studlee2](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/278dde/32.png) [@studlee2](https://www.ruby-forum.com/u/studlee2)\
**Post date:** [July 1, 2010, 9:53pm UTC](https://www.ruby-forum.com/t/running-a-shell-command-from-ruby/190979/1 "2010-07-01T21:53:46Z")

</div>

I am experimenting with running bash commands from within ruby. The  
commands should be in an array, separated internally with semicolons.

The problem is that they do not get executed.

My script:

* * *

## #!/usr/bin/ruby script1=[“touch ~/ruby/f1;touch ~/ruby/f2”] #addl array elements to be added puts script1[0].split(/;/) do |k| puts k system(k) end

The output from “puts k” looks good.  
But why do the files f1 and f2 not get created?

I realize that executing commands this way in ruby may be bad practise,  
but at least, why do the commands not execute?

Thanks in advance.  
Steve.

---

<div class="post-metadata">

**Author:** ![studlee2](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/278dde/32.png) [@studlee2](https://www.ruby-forum.com/u/studlee2)\
**Post date:** [July 2, 2010, 12:01am UTC](https://www.ruby-forum.com/t/running-a-shell-command-from-ruby/190979/2 "2010-07-02T00:01:57Z")

</div>

> script1=[“touch ~/ruby/f1;touch ~/ruby/f2”] #addl array elements to  
> But why do the files f1 and f2 not get created?

Does the directory ~/ruby/ already exist on your machine ?

Cheers,

---

<div class="post-metadata">

**Author:** ![studlee2](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/278dde/32.png) [@studlee2](https://www.ruby-forum.com/u/studlee2)\
**Post date:** [July 2, 2010, 1:43am UTC](https://www.ruby-forum.com/t/running-a-shell-command-from-ruby/190979/3 "2010-07-02T01:43:01Z")

</div>

> ## #!/usr/bin/ruby script1=[“touch ~/ruby/f1;touch ~/ruby/f2”] #addl array elements to be added puts script1[0].split(/;/) do |k| puts k system(k) end

> The output from “puts k” looks good.

Your block is not being called. I think the output you are seeing the is  
from the first “puts”, not the “puts” inside the block.

You need to call “each” on the Array returned by split, like this:

puts script1[0].split(/;/).each do |k|  
puts k  
system(k)  
end

–Brian

---

<div class="post-metadata">

**Author:** ![studlee2](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/278dde/32.png) [@studlee2](https://www.ruby-forum.com/u/studlee2)\
**Post date:** [July 2, 2010, 2:02am UTC](https://www.ruby-forum.com/t/running-a-shell-command-from-ruby/190979/4 "2010-07-02T02:02:34Z")

</div>

On Thu, Jul 1, 2010 at 2:53 PM, Steve P. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid)  
wrote:

> be added  
> but at least, why do the commands not execute?
> 
> ## Thanks in advance. Steve.
> 
> Posted via [http://www.ruby-forum.com/](http://www.ruby-forum.com/).

It has to do with block bindings. do … end bind to the furthest left  
method call on the line, so in this case, the block is being passed to  
the  
puts method, not the split method.

def puts( \*args , &block )  
super “puts received: #{args.inspect}, and #{block ? ‘a’ : ‘no’}  
block.”  
end

script1=[“touch ~/ruby/f1;touch ~/ruby/f2”] #addl array elements to  
be  
added  
puts script1[0].split(/;/) do |k|  
puts k  
system(k)  
end

---

<div class="post-metadata">

**Author:** ![studlee2](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/278dde/32.png) [@studlee2](https://www.ruby-forum.com/u/studlee2)\
**Post date:** [July 2, 2010, 3:52am UTC](https://www.ruby-forum.com/t/running-a-shell-command-from-ruby/190979/5 "2010-07-02T03:52:48Z")

</div>

Jean-Julien F. wrote:

> > script1=[“touch ~/ruby/f1;touch ~/ruby/f2”] ï¿½ ï¿½#addl array elements to  
> > But why do the files f1 and f2 not get created?
> 
> Does the directory ~/ruby/ already exist on your machine ?
> 
> Cheers,

Yes. It is where the ruby script is stored so I know it exists.  
Thanks.

---

<div class="post-metadata">

**Author:** ![studlee2](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/278dde/32.png) [@studlee2](https://www.ruby-forum.com/u/studlee2)\
**Post date:** [July 2, 2010, 2:23am UTC](https://www.ruby-forum.com/t/running-a-shell-command-from-ruby/190979/6 "2010-07-02T02:23:38Z")

</div>

On Thu, Jul 1, 2010 at 7:02 PM, Josh C. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> > #!/usr/bin/ruby
> 
> It has to do with block bindings. do … end bind to the furthest left  
> script1=[“touch ~/ruby/f1;touch ~/ruby/f2”] #addl array elements to be  
> added  
> puts script1[0].split(/;/) do |k|  
> puts k  
> system(k)  
> end

Here is a solution that creates the files.

* * *

script1=[“touch ~/f1;touch ~/f2”] #addl array elements to be added  
script1[0].split(/;/).each do |k|  
puts k  
system k  
end

* * *

Note that {} has the kind of binding that you were looking for, but that  
split does not take a block (which is why I added the each method).

though I don’t understand your format, are you wanting them to be  
separated  
by being elements in an array, or by splitting a string on semicolons?  
Right  
now, any other elements in this array will be ignored, because you only  
look  
at the one in index zero. (what is the point of the Array?)

But you also have an issue if you split on semicolons, that assumes all  
semicolons are valid delimiters. Depending on context, this may not be  
the  
case. For example, what if the String was:  
%{echo “if ARGV.empty? ; puts ‘no args’ else puts ‘got args’ end” \>  
argchecker.rb ; ruby argchecker.rb 1 2 3 ; ruby argchecker.rb}

Then you want it to find these commands  
[  
"echo "if ARGV.empty? ; puts ‘no args’ else puts ‘got args’ end" \>  
argchecker.rb ",  
" ruby argchecker.rb 1 2 3 “,  
" ruby argchecker.rb”  
]

But split(‘;’) will give you these commands  
[  
"echo "if ARGV.empty? ",  
" puts ‘no args’ else puts ‘got args’ end" \> argchecker.rb ",  
" ruby argchecker.rb 1 2 3 “,  
" ruby argchecker.rb”  
]

I think the best solution (easiest to implement, least likely to have  
bugs,  
most straightforward) is to keep each command separated in the Array,  
and  
not try to pull them from the string. If you do need to do that, you  
must  
either be careful to avoid using a semicolon in a way that is not a  
command  
delimiter, or you must find/write a parser so that you can determine  
where  
commands begin and end. I suppose you could also pick a different  
delimiter  
that is really unlikely to ever show up outside of the delimiter  
context.  
Some obscure unicode character, maybe.

---

<div class="post-metadata">

**Author:** ![studlee2](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/278dde/32.png) [@studlee2](https://www.ruby-forum.com/u/studlee2)\
**Post date:** [July 2, 2010, 4:09am UTC](https://www.ruby-forum.com/t/running-a-shell-command-from-ruby/190979/7 "2010-07-02T04:09:30Z")

</div>

Josh C. wrote:

> On Thu, Jul 1, 2010 at 7:02 PM, Josh C. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:
> 
> > > #!/usr/bin/ruby
> > 
> > It has to do with block bindings. do … end bind to the furthest left  
> > script1=[“touch ~/ruby/f1;touch ~/ruby/f2”] #addl array elements to be  
> > added  
> > puts script1[0].split(/;/) do |k|  
> > puts k  
> > system(k)  
> > end
> 
> Here is a solution that creates the files.
> 
> * * *
> 
> script1=[“touch ~/f1;touch ~/f2”] #addl array elements to be added  
> script1[0].split(/;/).each do |k|  
> puts k  
> system k  
> end
> 
> * * *
> 
> Note that {} has the kind of binding that you were looking for, but that  
> split does not take a block (which is why I added the each method).
> 
> though I don’t understand your format, are you wanting them to be  
> separated  
> by being elements in an array, or by splitting a string on semicolons?

My idea, as a learning exercise only,was to prove to myself that I could  
use an array of strings to contain “multiple” bash commands in “each”  
array element. Of course, my use of a “;” to delimit is probably ill  
advised, but was done merely for a proof of concept.

Now that with the addition of “.each”, it works and mystery (for me)  
solved.

I will have to study your code below more.

Thanks to all.  
Steve.

> Right  
> now, any other elements in this array will be ignored, because you only  
> look  
> at the one in index zero. (what is the point of the Array?)
> 
> But you also have an issue if you split on semicolons, that assumes all  
> semicolons are valid delimiters. Depending on context, this may not be  
> the  
> case. For example, what if the String was:  
> %{echo “if ARGV.empty? ; puts ‘no args’ else puts ‘got args’ end” \>  
> argchecker.rb ; ruby argchecker.rb 1 2 3 ; ruby argchecker.rb}
> 
> Then you want it to find these commands  
> [  
> "echo "if ARGV.empty? ; puts ‘no args’ else puts ‘got args’ end" \>  
> argchecker.rb ",  
> " ruby argchecker.rb 1 2 3 “,  
> " ruby argchecker.rb”  
> ]
> 
> But split(‘;’) will give you these commands  
> [  
> "echo "if ARGV.empty? ",  
> " puts ‘no args’ else puts ‘got args’ end" \> argchecker.rb ",  
> " ruby argchecker.rb 1 2 3 “,  
> " ruby argchecker.rb”  
> ]
> 
> I think the best solution (easiest to implement, least likely to have  
> bugs,  
> most straightforward) is to keep each command separated in the Array,  
> and  
> not try to pull them from the string. If you do need to do that, you  
> must  
> either be careful to avoid using a semicolon in a way that is not a  
> command  
> delimiter, or you must find/write a parser so that you can determine  
> where  
> commands begin and end. I suppose you could also pick a different  
> delimiter  
> that is really unlikely to ever show up outside of the delimiter  
> context.  
> Some obscure unicode character, maybe.

---

<div class="post-metadata">

**Author:** ![studlee2](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/278dde/32.png) [@studlee2](https://www.ruby-forum.com/u/studlee2)\
**Post date:** [July 2, 2010, 3:56am UTC](https://www.ruby-forum.com/t/running-a-shell-command-from-ruby/190979/8 "2010-07-02T03:56:54Z")

</div>

Brian B. wrote:

> > ## #!/usr/bin/ruby script1=[“touch ~/ruby/f1;touch ~/ruby/f2”] #addl array elements to be added puts script1[0].split(/;/) do |k| puts k system(k) end
> 
> > The output from “puts k” looks good.
> 
> Your block is not being called. I think the output you are seeing the is  
> from the first “puts”, not the “puts” inside the block.
> 
> You need to call “each” on the Array returned by split, like this:
> 
> puts script1[0].split(/;/).each do |k|  
> puts k  
> system(k)  
> end
> 
> –Brian

Brian, you were right.

Stupid of me not to think of the .each method.

Thank you!  
Steve.

revised script:

script1=[“touch /home/holocene/ruby/f1;touch /home/holocene/ruby/f2”]  
script1.length.times do |cnt|  
puts “script1 item #{cnt}”  
script1[0].split(/;/).each do |k|  
puts k  
system(k)  
end

end
