views:

305

answers:

8

Since I am conversant in Ruby, I am about to script a few things on OSX using it. But then I thought, perhaps I am missing the boat. I know a lot of reasons to prefer Ruby over Bash (or whatever sh-compatible command language interpreter), but I don't know any reasons not to. What is the upside of programming the shell directly?

I intend to take advantage of system commands using system whenever necessary.

Note: I already know that Ruby won't always be there, but I'm interested in mostly technical, semantic and syntactic criteria.

Edit: By Ruby not always being there, I mean that it is not a standard part of all *nix distributions, unlike vi.

+9  A: 

The shell's programming language is awful for all but one thing.

Pipelines.

The shell's programming language for pipelines totally rocks.

The |, & and ; operators, plus () and ``` form a tidy little language for describing pipelines.

a & b is concurrent

a ; b is sequential

a | b is a pipeline where a feeds b

That part of shell programming rocks.

Think of ( a & b & c ) | tee capture | analysis as the kind of thing that's hard to express in Python (or Ruby). You can do much of this with iterpipes, but not quite all of it.

Much of the rest you can live without, and use Python (or Ruby) and you'll be happier and more productive.

The biggest thing to watch out for is anything involving expr at the shell level. As soon as you start trying to do "calculations", you've crossed out of the shell's sweet spot and you should stop programming in the shell and rethink what you're doing.

S.Lott
Is there no way to pipe an input stream to an output stream from inside a script in Python (or Ruby, if you know)?
Yar
And thus working with files and text is a breeze.
Pepijn
@yar: Pipelines are easy to setup in Python (and probably easy in Ruby). But nowhere near as simple as this.
S.Lott
The edit for expr is great, thanks for that.
Yar
@SLott you should have a look at python [1]iterpipes. With it pipes rocks with python and are much more secure than using shell.[1] http://lateral.netmanagers.com.ar/weblog/posts/BB860.html
kriss
@kriss: Nice. That makes Python a close competitor with the shell for this kind of thing. The iterpipes notation is equally terse and elegant for the things it does. It doesn't do as much as the shell, but it's a start and covers the nastiest case well.
S.Lott
@Slott, the shell's programming language is awful, yes, but that's in the past. there are shells that have better/more features than others as well, eg zsh.
ghostdog74
@ghostdog74: Even zsh's programming language just a subset of what's available in Python or Ruby. The question is simply "What's being lost" The answer is that very little is being lost; shell languages are intentionally limited. However the pipeline and "programming in-the-large" features are difficult to find outside the shell.
S.Lott
@Slott, so can you advise on what are the "limitations" as pertaining to shells like zsh vs Python's shell. (note: Its Python's shell, don't include modules) ? the last time i checked, programming constructs like associative arrays, floating point maths are already incorporated.
ghostdog74
I can't understand a distinction between Python "shell" somehow excluding "modules". If by "shell" you mean the core language, does that include the `__builtins__` module? If we limit Python in artificial ways, why not also limit ZSH in equally odd and artificial ways. The point of Python is to have the *entire* language available, not a confusing subset. ZSH lacks object class definition, extensible collection types to start with. It also lacks a large collection of useful, sophisticated modules.
S.Lott
yes, i am referring to what the Python/Ruby interpreter can do by itself (__builtins__) vs zsh/bash (no external *nix tools). If you compare it this way, its "fairer". If you want to bring in collections, modules for comparison, then for the shell, you have to include tools like awk, grep, sed. etc. These are considered the "modules" for the shell since they are "external" and these tools have been revolving along with shell since long ago. Of course, wrt OO, the shell is definitely not one to talk about. (but that doesn't mean you can't "simulate" OO in shell, or use a OO shell.)
ghostdog74
@ghostdog74: Fair is *not* the point. The point is to have an effective environment for scripting. Python and Ruby do a lot -- a huge amount -- but there is one thing they do poorly. The point is not "fair". The point is *not* to randomly discard numerous language features. The point is to compare the complete suite of tools that's available. Python and Ruby fall short of the shell in one area.
S.Lott
@Slott, so if i get you correct, you are saying the shell is not "an effective environment for scripting" ? All basic stuffs we do daily, eg parsing files, manipulating strings, moving/copying files, getting web pages, etc can be done with Python/Ruby and shell. please define "The point is not to randomly discard numerous language features.". what shell features are randomly discarded?
ghostdog74
btw, am not trying to be funny or anything, just wanting to get different opinions on this from others like yourself
ghostdog74
@ghostdog74: You asked to compare something called "Python's shell, don't include modules". You can't discard a random feature of Python ("modules"). The point is to compare *all* of Python against *all* of a shell language. Python is much more convenient for everything but creating complex multiprocessing pipelines. For creating complex multiprocessing pipelines, the shell has an advantage. If you switch to using Python that's the one thing you give up.
S.Lott
yes, then it agree with this pt you said: "The point is to compare all of Python against all of a shell language.". In this case, for example, the re module vs sed/awk's regex. ftplib vs ftp client, shutil vs cp/mv/rm etc.. that's what it means when i say "fair"
ghostdog74
@ghostdog74: External programs like sed and awk are not part of the shell language. If you want to call that part of the shell, those are *also* part of Python, since Python does everything the shell does. And more. Except for one specific thing that Python is clumsy at.
S.Lott
@Slott, although sed/awk etc are "external" but they are called by shell to perform task. They are some what like the shell's "modules". You can treat it as though I am "importing regex" into shell programming. That makes no difference when you call "external" re module in Python. re is not part of the Python shell, so i call it "external". When i compare it like that, i call it "fair". another example of "fair", if Python can do GUI, like tkinter, wxPython, then with the shell, i can always make use of tools like xdialog/dialog (among many others).
ghostdog74
@ghostdog74. You're conflating a lot of confusing things to make some kind of point. I assume that your point is that the shell is just as good as Python. Which has nothing to do with this question. The question can be read above. What you give up when you switch to Python is simple. You give up nice pipelining. Please focus on the question. The "shell does everything python does" is not part of this question. And -- because of the number of weird restrictions you're creating -- very hard to follow.
S.Lott
yes, my point is the shell is just as good as Python, and also to refute your point on "Much of the rest you can live without, and use Python (or Ruby) and you'll be happier and more productive. The biggest thing to watch out for is anything involving expr at the shell level. As soon as you start trying to do "calculations", you've crossed out of the shell's sweet spot and you should stop programming in the shell and rethink what you're doing.". You did say this, don't you? you can do "calculations" just as good as Python using bc/awk. that's my point.
ghostdog74
@ghostdog74: Sigh. You keep adjusting the definitions. The shell is a process which forks other processes. Let's stick to a single process, please. The shell -- as a single process -- is dreadful. Adding the capability to use other processes reduces the horror. Python -- as a single process -- does everything the shell does and a lot more -- without adding new processes to the mix. Further, the shell never allows class definitions. The shell does not do as much as Python. Please do not add other processes. They are not equivalent to "modules".
S.Lott
@Slott, i am not talking about OP's question or the issue of forking process. I am referring to your comments that i highlighted, which is so untrue. you should think twice before putting up such comments in future.
ghostdog74
@ghostdog74: I'm utterly lost as to what point you're making. Could you perhaps open a question on whatever your point is?
S.Lott
+2  A: 

The core functionality in bash is to run other command line applications. Making those programs interact with each other etc. This is not what ruby is designed for (right?).

Joakim Elofsson
Isn't it bad to answer a question with an answer?
Yar
answer with an answer, how else would one answer?
Joakim Elofsson
A: 

Shell's programming languages have a very small footprint and very few dependencies. Beside that I can't see much point using it. Personnaly I prefer using Perl or python for such tasks.

kriss
+1  A: 

I don't see any problem with Ruby. You can use the back-tick instead of system and insert things inline like

`cp ${source} ${dest}` 

Also, you can easily get the contents of stdout (not sure about stdin) and form your own little pipelining thing.

I think Ruby is a win for doing scripting stuff, but less so as a general shell because of the clunky bit of always having to remember to put back-ticks to execute commands.

Earlz
Without stdin how can you do piping?
Yar
I'm sure you can get access to stdin, I'm just saying I'm not sure how.
Earlz
Okay thanks for your answer (I had already upvoted it) and I'll look for an answer to that piping question here.
Yar
Thanks @Earlz, you inspired me. Here's my answer after 10 minutes of dinking around: `IO.popen("grep -i what", "w").write ( IO.popen('find . ').read )`
Yar
@Earlz today I was messing around with backticks, and it's really a huge help. You can even do weird stuff like `puts `find .``
Yar
@yar, yup thats Ruby for you, everything has a result :)
Earlz
+2  A: 

Directly writing Posix or bash script works out well for operations that loop over lists of files. Things like

find . -name \*.htm | while read x; do
   # whatever
done

The shell can do command substitution and simple parameter transformations reasonably well. Shell procedures allow fairly complex programs to be reasonably modular.

The transition to something like Ruby happens when some kind of internal data structure is needed. The shell is a macro processor, so it is capable of something like "metaprogramming" where you make up variables names. Some versions of bash have arrays and all versions can "metaprogram" variable names where the index is part of the name.

But it's 100% hack and even the built-in arrays are crude. Once decisions have to be made and data structures retained, it's time to switch to Ruby.

DigitalRoss
Interesting, thanks +1
Yar
+1  A: 

The comments about how the shell handles piping are spot on. However, if you are interested in a rubyish approach to the shell you might look at rush. There are immediate observations (outside of how piping is handled) such as paths are now handled in an entirely different way, but if what you want is the ease of ruby things like iterators and blocks you have that at your fingertips.

Likely not a full replacement in any case, but it might serve your purpose.

[Edit] A quick look around turned up ipython which looks (at a cursory glance) to give more of the natural feel of a shell environment which may or may not be an incentive for you.

ezpz
Rush is basically too cool! +1 However, my problem is that it I'd be investing time learning a shell that would require me to have that shell. You can't always get root access to install a gem on every system. With the Ruby scripting question, I'm imagining using the shell for shell-ish things and using Ruby for everything else. I assume that if I'm doing any real scripting, I have rights to install Ruby (hope that makes sense)
Yar
@ezpz, Rush is awesome, at least as a library for scripting. Of course you're adding dependency, but... that happens.
Yar
+1  A: 

Ruby has a massive advantage: you know Ruby and (I assume) you don't know Bash that well!

Personally I use Ruby for complex scripts and Bash for simple ones -- the breakpoint for me is usually anything that actually has a proper set of command line parameters -- but then, I know both Bash and Ruby.

I would advise you to use Bash for anything that is simple enough that you can work it out on the commandline beforehand, for example:

who |grep -i admin |cut -c10-20 

-- and use Ruby for anything else

Shadowfirebird
thanks for that, more or less what I was imagining
Yar
A: 

@OP, if you want to compare Ruby vs Shell, compare using Ruby's interpreter( without libraries/modules). ie compare its in-builts against the shell. Otherwise, they are almost the same. Why? For example, if you want to do advanced maths other than those provided by the shell, the shell can use bc/awk/dc. Those are the math "libraries" for the shell. If you want date structures such as associative arrays, you can use awk. (equivalent to hashes in ruby). In modern bash shell, there are also associative arrays. You can think of *nix external tools (eg wc,grep,sed etc and those in /usr/bin/, /usr/sbin etc) as the shell's "libraries".

Lastly, if you intend to use system() a lot in Ruby, i suggest using the shell as one of them mentioned, the shell excels in pipes. etc..

ghostdog74