352

What are the differences between shell languages like Bash (bash), Z shell (zsh), Fish (fish) and the scripting languages above that makes them more suitable for the shell?

When using the command line, the shell languages seem to be much easier. It feels for me much smoother to use bash for example than to use the shell profile in IPython, despite reports to the contrary. I think most will agree with me that a large portion of medium to large scale programming is easier in Python than in Bash. I use Python as the language I am most familiar with. The same goes for Perl and Ruby.

I have tried to articulate the reason, but I am unable to, aside from assuming that the treatment of strings differently in both has something to do with it.

The reason of this question is that I am hoping to develop a language usable in both. If you know of such a language, please post it as well.

As S.Lott explains, the question needs some clarification. I am asking about the features of the shell language versus that of scripting languages. So the comparison is not about the characteristics of various interactive (REPL) environments such as history and command line substitution. An alternative expression for the question would be:

Can a programming language that is suitable for design of complex systems be at the same time able to express useful one-liners that can access the file system or control jobs? Can a programming language usefully scale up as well as scale down?

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Muhammad Alkarouri
  • 23,884
  • 19
  • 66
  • 101

12 Answers12

480

There are a couple of differences that I can think of; just thoughtstreaming here, in no particular order:

  1. Python & Co. are designed to be good at scripting. Bash & Co. are designed to be only good at scripting, with absolutely no compromise. IOW: Python is designed to be good both at scripting and non-scripting, Bash cares only about scripting.

  2. Bash & Co. are untyped, Python & Co. are strongly typed, which means that the number 123, the string 123 and the file 123 are quite different. They are, however, not statically typed, which means they need to have different literals for those, in order to keep them apart.
    Example:

                    | Ruby             | Bash    
    -----------------------------------------
    number          | 123              | 123
    string          | '123'            | 123
    regexp          | /123/            | 123
    file            | File.open('123') | 123
    file descriptor | IO.open('123')   | 123
    URI             | URI.parse('123') | 123
    command         | `123`            | 123
    
  3. Python & Co. are designed to scale up to 10000, 100000, maybe even 1000000 line programs, Bash & Co. are designed to scale down to 10 character programs.

  4. In Bash & Co., files, directories, file descriptors, processes are all first-class objects, in Python, only Python objects are first-class, if you want to manipulate files, directories etc., you have to wrap them in a Python object first.

  5. Shell programming is basically dataflow programming. Nobody realizes that, not even the people who write shells, but it turns out that shells are quite good at that, and general-purpose languages not so much. In the general-purpose programming world, dataflow seems to be mostly viewed as a concurrency model, not so much as a programming paradigm.

I have the feeling that trying to address these points by bolting features or DSLs onto a general-purpose programming language doesn't work. At least, I have yet to see a convincing implementation of it. There is RuSH (Ruby shell), which tries to implement a shell in Ruby, there is rush, which is an internal DSL for shell programming in Ruby, there is Hotwire, which is a Python shell, but IMO none of those come even close to competing with Bash, Zsh, fish and friends.

Actually, IMHO, the best current shell is Microsoft PowerShell, which is very surprising considering that for several decades now, Microsoft has continually had the worst shells evar. I mean, COMMAND.COM? Really? (Unfortunately, they still have a crappy terminal. It's still the "command prompt" that has been around since, what? Windows 3.0?)

PowerShell was basically created by ignoring everything Microsoft has ever done (COMMAND.COM, CMD.EXE, VBScript, JScript) and instead starting from the Unix shell, then removing all backwards-compatibility cruft (like backticks for command substitution) and massaging it a bit to make it more Windows-friendly (like using the now unused backtick as an escape character instead of the backslash which is the path component separator character in Windows). After that, is when the magic happens.

They address problem 1 and 3 from above, by basically making the opposite choice compared to Python. Python cares about large programs first, scripting second. Bash cares only about scripting. PowerShell cares about scripting first, large programs second. A defining moment for me was watching a video of an interview with Jeffrey Snover (PowerShell's lead designer), when the interviewer asked him how big of a program one could write with PowerShell and Snover answered without missing a beat: "80 characters." At that moment I realized that this is finally a guy at Microsoft who "gets" shell programming (probably related to the fact that PowerShell was neither developed by Microsoft's programming language group (i.e. lambda-calculus math nerds) nor the OS group (kernel nerds) but rather the server group (i.e. sysadmins who actually use shells)), and that I should probably take a serious look at PowerShell.

Number 2 is solved by having arguments be statically typed. So, you can write just 123 and PowerShell knows whether it is a string or a number or a file, because the cmdlet (which is what shell commands are called in PowerShell) declares the types of its arguments to the shell. This has pretty deep ramifications: unlike Unix, where each command is responsible for parsing its own arguments (the shell basically passes the arguments as an array of strings), argument parsing in PowerShell is done by the shell. The cmdlets specify all their options and flags and arguments, as well as their types and names and documentation(!) to the shell, which then can perform argument parsing, tab completion, IntelliSense, inline documentation popups etc. in one centralized place. (This is not revolutionary, and the PowerShell designers acknowledge shells like the DIGITAL Command Language (DCL) and the IBM OS/400 Command Language (CL) as prior art. For anyone who has ever used an AS/400, this should sound familiar. In OS/400, you can write a shell command and if you don't know the syntax of certain arguments, you can simply leave them out and hit F4, which will bring a menu (similar to an HTML form) with labelled fields, dropdown, help texts etc. This is only possible because the OS knows about all the possible arguments and their types.) In the Unix shell, this information is often duplicated three times: in the argument parsing code in the command itself, in the bash-completion script for tab-completion and in the manpage.

Number 4 is solved by the fact that PowerShell operates on strongly typed objects, which includes stuff like files, processes, folders and so on.

Number 5 is particularly interesting, because PowerShell is the only shell I know of, where the people who wrote it were actually aware of the fact that shells are essentially dataflow engines and deliberately implemented it as a dataflow engine.

Another nice thing about PowerShell are the naming conventions: all cmdlets are named Action-Object and moreover, there are also standardized names for specific actions and specific objects. (Again, this should sound familar to OS/400 users.) For example, everything which is related to receiving some information is called Get-Foo. And everything operating on (sub-)objects is called Bar-ChildItem. So, the equivalent to ls is Get-ChildItem (although PowerShell also provides builtin aliases ls and dir – in fact, whenever it makes sense, they provide both Unix and CMD.EXE aliases as well as abbreviations (gci in this case)).

But the killer feature IMO is the strongly typed object pipelines. While PowerShell is derived from the Unix shell, there is one very important distinction: in Unix, all communication (both via pipes and redirections as well as via command arguments) is done with untyped, unstructured strings. In PowerShell, it's all strongly typed, structured objects. This is so incredibly powerful that I seriously wonder why noone else has thought of it. (Well, they have, but they never became popular.) In my shell scripts, I estimate that up to one third of the commands is only there to act as an adapter between two other commands that don't agree on a common textual format. Many of those adapters go away in PowerShell, because the cmdlets exchange structured objects instead of unstructured text. And if you look inside the commands, then they pretty much consist of three stages: parse the textual input into an internal object representation, manipulate the objects, convert them back into text. Again, the first and third stage basically go away, because the data already comes in as objects.

However, the designers have taken great care to preserve the dynamicity and flexibility of shell scripting through what they call an Adaptive Type System.

Anyway, I don't want to turn this into a PowerShell commercial. There are plenty of things that are not so great about PowerShell, although most of those have to do either with Windows or with the specific implementation, and not so much with the concepts. (E.g. the fact that it is implemented in .NET means that the very first time you start up the shell can take up to several seconds if the .NET framework is not already in the filesystem cache due to some other application that needs it. Considering that you often use the shell for well under a second, that is completely unacceptable.)

The most important point I want to make is that if you want to look at existing work in scripting languages and shells, you shouldn't stop at Unix and the Ruby/Python/Perl/PHP family. For example, Tcl was already mentioned. Rexx would be another scripting language. Emacs Lisp would be yet another. And in the shell realm there are some of the already mentioned mainframe/midrange shells such as the OS/400 command line and DCL. Also, Plan9's rc.

Matt Kantor
  • 1,704
  • 1
  • 19
  • 37
Jörg W Mittag
  • 363,080
  • 75
  • 446
  • 653
  • 2
    A very good answer to both sections of the question. About points 2 and 4: Is that because of static typing as such, or is it because of a casting operation? In most non-shell languages (static or dynamic) that I know of, `123` cannot define two different types. Also do you have a link explaining Powershell's Adaptive Type System? Google doesn't seem to throw at me anything I could understand. – Muhammad Alkarouri Sep 06 '10 at 00:34
  • 2
    Great answer! Do you remember the link to that interview with Jeffrey Snover? – Mauricio Scheffer Nov 08 '10 at 14:43
  • 1
    This sounds amazing, so is there a PowerShell-esque implementation for UNIX/Linux that can replace bash? – Dave Jan 01 '11 at 22:27
  • EVE-Online uses python primarily (with a C++ backend) and must be over millions of LOC. – codebliss Jan 01 '11 at 23:29
  • 11
    13 votes in 4 months and then 84 in 20 hours? Did I get reddited or something? @Mauricio Scheffer: I skimmed through almost all the videos on Channel9, even back to when PS was still called Monad, but nothing jumped out at me, sorry. @Dave: There is a project called [Pash (PoSh + Bash)](http://PaSh.SF.Net/), but that has only had one release three years ago. [BUSH](http://BUSH.SF.Net/) and [FISH](http://FISH.SF.Net/) move away from Bourne *syntax*, but they still deal in text. @codebliss: The question was about Python as a *shell* language. The interesting number here is *one LOC*. – Jörg W Mittag Jan 02 '11 at 00:11
  • 2
    @Muhammad Alkarouri: Basically, since PowerShell *knows* that, say, the first argument to a `repeat` loop is the number of iterations and the second argument is the code to repeat, it *knows* that in `repeat 123 123` the first `123` is a number and the second is a command. (Completely made up example.) It is basically overloading the literals based on their result type, which sounds strange at first, but is actually what happens with lambda literals in C# as well. (They get interpreted as either `Action/Func` or `Expression` depending on what type of variable/parameter they are bound to.) – Jörg W Mittag Jan 02 '11 at 00:24
  • Aah, that explains it: http://Programming.Reddit.Com/comments/eui2x/ – Jörg W Mittag Jan 02 '11 at 00:26
  • @Jörg W Mittag: you did get reddited, mea culpa. And thanks for the response to the comments. – Muhammad Alkarouri Jan 02 '11 at 00:36
  • 4
    @Muhammad Alkarouri: Another way to look at it: PowerShell doesn't support polymorphism or overloading. In a language with polymorphism, the language decides which procedure to execute based on the types of the arguments. (E.g. in `x.ToString()` in depends on the type of `x` *which* `ToString()` gets executed.) In PowerShell, it's exactly the dual: the language decides as what types to interpret the arguments, based on the procedure. Yet *another* interpretation is that the grammar gets built dynamically based on the argument types, so there is only way to parse the tokens. – Jörg W Mittag Jan 02 '11 at 00:47
  • @Jörg W Mittag: Can it be seen as a sort of type inference? – Muhammad Alkarouri Jan 02 '11 at 01:04
  • 2
    The Wikipedia page has some useful examples of PowerShell commands: http://en.wikipedia.org/wiki/Windows_PowerShell#Examples – mjs Jan 02 '11 at 14:32
  • 2
    @Jorg ... the power of Unix shells is that all the hard work is done by plain executables, many of which are part of POSIX or just a defacto standard (find me a Unix box without Perl, grep or awk on it). "cmdlets" are written on top of .NET using special conventions described only 5 years ago. What good does strong-typing do if you have to search/write a cmdlet for ImageMagick? ... and contrary to what Microsoft throws over the fence, the standard Unix tools don't get reinvented every couple of years. – Alexandru Nedelcu Jan 03 '11 at 07:20
  • zomg gr8 answer +1 – Samuel Katz Mar 13 '11 at 00:58
  • This was quite well-written to the point that I won't avoid trying PowerShell anymore. I really enjoyed number 4, though I wish you'd expanded upon it more like the rest. But that's just because you had pulled me in as a listener. – Alex Nye Dec 03 '12 at 05:34
  • 3
    @Alexandru: PowerShell is (hence the name) still a shell and thus makes executing programs easy (albeit not totally painless depending on arguments that may require quoting). So you can use ImageMagick just like you would anywhere else without first having to write/find a cmdlet or a PowerShell function that wraps it. *But* a PowerShell-native implementation can be so much cooler, e.g. by passing image objects around and implementing image filters as cmdlets. I'm still thinking of writing something that would allow things like `Load-Image foo.bmp | Apply-Blur -Radius 5 | Save-Image x.png`. – Joey Feb 15 '13 at 13:03
  • 1
    "Bash & Co. are designed to scale down to 10 character programs" <- loved this one – michaelmeyer May 25 '13 at 17:12
  • @doukremt: Thanks! I didn't come up with that entirely by myself, it is inspired by a comment Jeffrey Snover (PowerShell lead architect) made in an interview. They were talking about the strong static type system of PS and the PS IDE and the fact that they wanted to design PS as a "proper" programming language to write large programs in, and the interviewer asked how big of a program one could write in PS. Snover replied: "80 characters." – Jörg W Mittag May 26 '13 at 00:16
  • So a ten pages long Powershell infomercial is voted as best answer even though it completely misses the question asked? – Profpatsch Feb 20 '14 at 16:05
  • 1
    Shall we port PowerShell to linux now? – CMCDragonkai Jun 13 '14 at 08:39
  • @CMCDragonkai: Too late: http://pash.sourceforge.net/ Also, http://sparforte.com/ is based on many of the same ideas in PowerShell. https://code.google.com/p/hotwire-shell/ was another implementation of (some) of those ideas. – Jörg W Mittag Jun 13 '14 at 12:06
60

It's cultural. The Bourne shell is almost 25 years old; it was one of the first scripting languages, and it was the first good solution to the central need of Unix admins. (I.e., a 'glue' to tie all the other utilities together and to do typical Unix tasks without having to compile a damn C program every time.)

By modern standards, its syntax is atrocious and its weird rules and punctuation-as-statement style (useful in the 1970s when every byte counted) make it hard for non-admins to penetrate it. But it did the job. The flaws and shortcomings were addressed by evolutionary improvements in its descendants (ksh, bash, zsh) without having to reconceive the ideas behind it. Admins stuck to the core syntax because, weird as it was, nothing else handled the simple stuff better without getting in the way.

For complex stuff, Perl came along and morphed into a sort of half-admin, half-application language. But the more complex something gets, the more it's seen as an application rather than admin work, so the business people tend to look for "programmers" rather than "admins" to do it, despite the fact that the right kind of geek tends to be both. So that's where the focus went, and the evolutionary improvements to the application capabilities of Perl resulted in...well, Python and Ruby. (That's an oversimplification, but Perl was one of several inspirations for both languages.)

Result? Specialization. Admins tend to think modern interpreted languages are too heavyweight for the things they're paid to do every day. And overall, they're right. They don't need objects. They don't care about data structures. They need commands. They need glue. Nothing else tries to do commands better than the Bourne shell concept (except maybe Tcl, which was already mentioned here); and Bourne is good enough.

Programmers -- who nowadays are having to learn about devops more and more -- look at the limitations of the Bourne shell and wonder how the hell anyone could put up with it. But the tools they know, while they certainly lean towards the Unixish style of I/O and file operations, aren't better for the purpose. I've written things like backup scripts and file renaming one-offs in Ruby, because I know it better than I know bash, but any dedicated admin could do the same thing in bash -- probably in fewer lines and with less overhead, but either way, it'd work just as well.

It's a common thing to ask "Why does everyone use Y when Z is better?" -- but evolution in technology, like evolution in everything else, tends to stop at good enough. The 'better' solution doesn't win unless the difference is viewed as a deal-breaking frustration. Bourne-type scripting might be frustrating to you, but for the people who use it all the time and for the jobs it was meant for, it's always done the job.

SFEley
  • 7,660
  • 5
  • 28
  • 31
  • I think it might serve as an inspiration for some future technology that will use, say, pipe (`|`) as the foundational concept. Much like Javascript was rebranded and revived with numerous modern languages and then `node.js`, the same might as well happen to shell scripts. – Sergey Orshanskiy Jun 22 '14 at 04:15
54

A shell language has to be easy to use. You want to type one-time throw away commands, not small programs. I.e., you want to type

ls -laR /usr

not

shell.ls("/usr", long=True, all=True, recursive=True)

This (also) means shell languages don't really care if an argument is an option, a string, a number or something else.

Also, programming constructs in shells are an add-on, and not even always build-in. I.e. consider the combination of if and [ in Bash or Bourne shell (sh), seq for generating sequences, and so on.

Finally, shells have specific needs that you need less, or differently in programming. I.e., pipes, file redirection, process/job control, and so on.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Ivo van der Wijk
  • 16,341
  • 4
  • 43
  • 57
  • Thanks for the answer, but these differences do not seem to me to be intrinsic to the language. It is very easy to design a library so in Python you say `shell.ls('usr', flags='laR')`. Even the `shell` bit and the `flags=` bit can be removed. I agree that things like redirection and process control are optimised in shells because of their relevance there. – Muhammad Alkarouri Sep 03 '10 at 16:56
  • 4
    You'll still need to do proper quoting and balance your parens. And you're providing a trivial argument here, what about "ls --sort=time -R /bin /usr", for example? – Ivo van der Wijk Jan 02 '11 at 21:17
  • Your point about running commands applies to Python but not all of the languages under consideration: for example, `\`ls -laR /usr\`` will do it in perl. – intuited Oct 31 '12 at 19:16
  • 8
    then you're not using perl but simply executing shell commands through perl. – Ivo van der Wijk Nov 08 '12 at 08:42
  • Ruby's un-required parens mean you could write a function that's *almost* as good as in bash: `ls :-laR, :/usr`. You've still got the commas and symbols (or strings), though. – Xiong Chiamiov Jun 03 '13 at 23:48
  • 1
    Shameless plug, I wrote a python library that hopefully makes python easier to use: https://github.com/houqp/shell.py – houqp May 01 '14 at 20:52
42

If you know of such a language, please post it as well.

Tcl is one such language. Mainly because it is designed to primarily be a shell interpreter for CAD programs. Here's one hardcore Python programmer's* experience of realising why Tcl was designed the way it was: I can't believe I'm praising Tcl

For me, I've written and have been using and improved Tcl shell (written in Tcl, of course) as my main Linux login shell on my homebrewed router: Pure Tcl readline

Some of the reasons I like Tcl in general has everything to do with the similarity of its syntax to traditional shells:

  1. At its most basic, Tcl syntax is command argument argument.... There's nothing else. This is the same as Bash, C shell or even DOS shell.

  2. A bareword is considered a string. This is again similar to traditional shells allowing you to write: open myfile.txt w+ instead of open "myfile.txt" "w+".

  3. Because of the foundations of 1 and 2, Tcl ends up with very little extraneous syntax. You write code with less punctuation: puts Hello instead of printf("Hello");. When writing programs you don't feel the hurt so much, because you spend a lot of time thinking about what to write. When you use a shell to copy a file you don't think you just type and having to type ( and " and , and ) and ; again and again gets annoying very quickly.

*Note: not me; I'm a hardcore Tcl programmer

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
slebetman
  • 109,858
  • 19
  • 140
  • 171
  • Very good! I forgot all about Tcl. I had a short introduction to it a long while ago, and I simply forgot that it was a perfectly good shell interface for some Cisco routers that I used a long time now. It looks like Tcl is the nearest to the sweet spot between them. I will switch to tclsh for a couple of days to see how it goes. – Muhammad Alkarouri Sep 03 '10 at 17:03
  • 1
    Now the slightly unflattering bit. Tcl is not as successful as other languages, can you say why? I remember not being happy with the `math` command, and probably OOP, but that was a long time ago. – Muhammad Alkarouri Sep 03 '10 at 17:06
  • For the first bit, I'd like to point out that tclsh is a really-really basic shell: no up-down-arrow history, no tab completion etc.. I would recommend you at least use `rlwrap tclsh` to wrap it in readline. Or even better, use my code linked above as your shell. For the second bit, I think it's because most programmers are uncomfortable with anything that doesn't look like C. Fun fact, Netscape originally implemented Tcl as the browser scripting language but management wanted something that looks like Java syntax (which is, again another C-like syntax). – slebetman Sep 03 '10 at 17:28
  • 1
    I did look at your code after I posted my comment, and I am going to use that. Speaking about insufficiently C-like languages, you have probably come across [this](http://james-iry.blogspot.com/2009/05/brief-incomplete-and-mostly-wrong.html) before. – Muhammad Alkarouri Sep 03 '10 at 22:07
  • TCL's problems as I recall were political. – chiggsy Jan 02 '11 at 01:38
  • Actually, the *really cool* thing about Tcl's syntax is not so much that it is like Bash, but that it is like Lisp S-Expressions, thus allowing powerful metalinguistic abstraction and syntactic metprogramming. – Jörg W Mittag Jun 18 '11 at 11:47
18

Who says they aren't? Take a look at Zoidberg. REPLs (Read Eval Print Loops) make crappy shells because every command must be syntactically correct, and running a program goes from being:

foo arg1 arg2 arg3

to

system "foo", "arg1", "arg2", "arg3"

And don't even get me started on trying to do redirection.

So, you need a custom shell (rather than a REPL) that understands commands and redirection and the language you want to use to bind commands together. I think zoid (the Zoidberg shell) does a pretty good job of it.

Philipp Claßen
  • 41,306
  • 31
  • 146
  • 239
Chas. Owens
  • 64,182
  • 22
  • 135
  • 226
  • 1
    Going to give zoid a try. Do you know, is there any amount of a base of people using as their primary shell? – Joel Berger Oct 26 '10 at 00:39
  • 1
    @Joel I doubt it. It was last updated on CPAN in 2006. It is hard to beat `bash`. It is ubiquitous, feature complete, and maintained. Shells like `zoid` are fun to play with, but I always return to `bash` or `ksh`. – Chas. Owens Oct 26 '10 at 12:42
  • 1
    Yeah, I also saw that it hasn't been maintained. I wonder what kind of brushing up it might need, I would be interested using a shell with that kind of power. – Joel Berger Oct 26 '10 at 12:56
  • 6
    I have actually fixed some of the major bugs (I am the new maintainer!). Check out [`Zoidberg`](http://p3rl.org/zoiduser) for all your Perl-based shell needs! – Joel Berger Feb 11 '12 at 18:19
  • Genuine question here: What's the difference between a Perl-based shell like the Zoidberg shell, and something that comes included with Raku, i.e. the [Raku REPL](https://course.raku.org/essentials/running-programs/from-repl/) ? – jubilatious1 Jan 29 '23 at 09:10
14

These answers inspired me to take over maintenance of the Perl-based shell Zoidberg. After some fixes, it is usable again!

Check out the user's guide or install Bundle::Zoidberg using your favorite CPAN client.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Joel Berger
  • 20,180
  • 5
  • 49
  • 104
11

No.


No, scripting languages are probably not suitable for shells.


The problem is the dichotomy between macro languages and, well, everything else.

The shell is in a category with other legacy macro languages such as nroff and m4. In these processors, everything is a string and the processor defines a mapping from input strings to output strings.

Certain boundaries are crossed in both directions in all languages, but it's usually quite clear whether a system's category is macro or, hmm, I'm not aware of an official term ... I will say "a real language".

So sure, you could type in all your commands in a language like Ruby, and it might even be a second-best choice to a real shell, but it will never be a macro language. There is too much syntax to respect. It takes too many quotes.

But the macro language has its own issues when you start programming in it, because too many compromises had to be made to get rid of all that syntax. Strings are typed in with no quotes. Various amounts of magic need to be re-introduced to inject the missing syntax. I did a code-golf in nroff once, just to be different. It was pretty strange. The source code to big implementations in macro languages is scary.

DigitalRoss
  • 143,651
  • 25
  • 248
  • 329
  • 1
    Thanks a lot! That is actually the missing point, the exact response to my "I have tried to articulate the reason but am unable to, aside from assuming that the treatment of strings differently in both has something to do with it.". It will be interesting to find out if any research about macro languages has been done. – Muhammad Alkarouri Aug 30 '11 at 09:41
7

Since both are formally programming languages, what you can do in one, you can do in the other. Actually it is a design emphasis issue. Shell languages are designed for interactive use, while scripting languages aren't.

The basic difference in the design is the storage of data between commands and the scope of variables. In Bash, etc. you have to jump through hoops to store a value (for example, commands like set a='something'), while in languages like Python you simply use an assignment statement (a = 'something'). When using the values in a shell language you have to tell the language that your want the value of the variable, while in scripting languages you have to tell the language when you want the immediate value of the string. This has effects when used interactively.

In a scripting language where ls was defined as a command

a = some_value

ls a*b  

(What does a mean? Does this mean some_value * (whatever b is) or do you mean 'a'anystring'b'?. In a scripting language the default is what is stored in memory for a.)

ls 'a*b'  Now means what the Unix ls a*b means.

In a Bash-like language

set a=some_value

ls a*b   means what the Unix ls a*b means.

ls $a*b  uses an explicit recall of the value of a.

Scripting languages make it easy to store and recall values and hard to have a transient scope on a value. Shell languages make it possible to store and recall values, but have a trivially transient scope per command.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
rob
  • 71
  • 1
  • 1
6

I think it's a question of parsing. Shell languages assume by default the normal $ xxx command means you mean a command to run. In Python and Ruby need you to do system("command") or what not.

It's not that they're unsuitable, just that nobody has really done it yet; at least I think so. Rush is an example attempt in Ruby, and Python has IPython or something like that.

rogerdpack
  • 62,887
  • 36
  • 269
  • 388
  • Thanks for the link. I have used ipython, and my first impression is that Rush looks a bit better, probably because of the fluent interface. I need to look at it a bit more. – Muhammad Alkarouri Sep 03 '10 at 16:59
3

You beg the question. Not everyone agrees that shell languages are superior. For one, _Why doesn't

Not long ago a friend asked me how to recursively search his PHP scripts for a string. He had a lot of big binary files and templates in those directories that could have really bogged down a plain grep. I couldn't think of a way to use grep to make this happen, so I figured using find and grep together would be my best bet.

  find . -name "*.php" -exec grep 'search_string' {} \; -print

Here's the above file search reworked in Ruby:

  Dir['**/*.php'].each do |path|
    File.open( path ) do |f|
      f.grep( /search_string/ ) do |line|
        puts path, ':', line
      end
    end
  end

Your first reaction may be, "Well, that's quite a bit wordier than the original." And I just have to shrug and let it be. "It's a lot easier to extend," I say. And it works across platforms.

Colonel Panic
  • 132,665
  • 89
  • 401
  • 465
  • 3
    `find . -name '*.php' | xargs -d \\n grep -l 'search_string'` will be faster for non-huge files by avoiding N invocations of `grep`. :) – intuited Oct 31 '12 at 19:58
  • 1
    The question isn't about writing shell-like scripts, its about the language that the shell executes. – Joel Berger Feb 03 '13 at 13:59
  • 3
    So you just replaced a 60 char script that is reasonably easy to read if you understand the syntax with a 125 char script (ignoring the additional whitespace and newlines you'll want to make the script actually readable) that isn't any clearer. Great example of why you don't want to use python or ruby. 99.999% of all scripts are things with exact specifications (or 1off jobs) that won't ever be extended. Powershell even has a nice syntax, allows for easy extensibility and is concise for the main job of scripts. – Voo Feb 04 '13 at 06:04
  • @Voo "that is reasonably easy to read if you understand the syntax"… and there you destroy your own argument. Aside from that, syntax not only needs to be understood, it also has to be _liked_ if you're going to choose use it repeatedly when there are competitors. I don't like Powershell's syntax, all that camel casing is horrible. YMMV. – ian Jul 14 '13 at 19:45
  • @intuited You can also use `find . -name "*.php" -exec grep -l 'search_string' {} +` to avoid N invocations of `grep` (although I think the `+` is non-portable). – Max Nanasy Aug 03 '13 at 21:11
  • @MaxNanasy, the `+` version of -exec is, in fact, POSIX compliant. – Charles Duffy Feb 24 '14 at 02:34
  • 2
    @alexis, both `xargs` (unless given a contrary flag) and `find -exec {} +` (as opposed to `-exec {} \;`) will fill out each invocation to the maximum argument length allowed, so no, it's less than N (where N is the number of items found). – Charles Duffy Feb 24 '14 at 02:36
  • The ruby is probably not very cross-platform, note the forward slashes. Forward slashes don't work on Windows. – Nate Symer Jun 11 '14 at 14:55
3

Scalability and extensibility? Common Lisp (you can even run CLISP, and possibly other implementations, as a login shell in Unix environments).

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
3

For the Windows users, I haven't yet felt the need for PowerShell, because I still use 4NT (now Take Command Console) from JP Software. It is a very good shell with lots of programming abilities. So it combines the best of both worlds.

When you take a look at, for example, IRB (the Ruby interpreter), it must be well possible to extend it with more one-liners to do daily scripted or mass file management and on the minute tasks.

peter
  • 41,770
  • 5
  • 64
  • 108