86

TL;DR; What are shell scripts? Is it a programming language / is there a programming language we use in shell scripts?


disclaimer: a bit offtopic
So bash stands for Bourne-again shell. A (Unix) Shell is a command line user interface or maybe one could call it an interpreter (?)

So I'm filling out an application for a new job and you get asked for experience of different programming languages and then there is this box at the bottom other experiences - I started typing python 2.7, powershell, bas... Wait! bash isn't a programming language - it's a console that can execute shell scripts... so... eh.... oh my god I have no idea!

boop
  • 7,413
  • 13
  • 50
  • 94
  • 7
    FWIW, please **do** include Bash as a programming language skill if you have it. After all, [scripting languages](https://en.wikipedia.org/wiki/Scripting_language) _are_ programming languages. Technically however, if you know enough scripting languages, you could list them separately if the document permits. After having had over a dozen Linux-based job interviews over the years, not one interviewer has asked me why I listed Bash as a programming language. If anything, they also wanted to see sed and awk in that list. – Asclepius Oct 29 '16 at 20:06
  • 1
    Not only a programming language, but **the best** programming language for many things. Those things that can be done simpler by calling other programs, and composing them. **Huge** time saver. Just make sure to keep the code broken into the smallest functions, otherwise it gets obscure to understand and test. – Alberto Salvia Novella Sep 11 '21 at 02:47
  • Yes, in the same way a rock is a hammer. – Bob Jun 22 '22 at 10:52

4 Answers4

83

We can say that yes, it is a programming language.

According to man bash, Bash is a "sh-compatible command language". Then, we can say a "command language" is "a programming language through which a user communicates with the operating system or an application".

From man bash:

DESCRIPTION

Bash is an sh-compatible command language interpreter that executes commands read from the standard input or from a file. Bash also incorporates useful features from the Korn and C shells (ksh and csh).

http://www.gnu.org/software/bash/

Bash is the GNU Project's shell. Bash is the Bourne Again SHell. Bash is an sh-compatible shell that incorporates useful features from the Korn shell (ksh) and C shell (csh). It is intended to conform to the IEEE POSIX P1003.2/ISO 9945.2 Shell and Tools standard. It offers functional improvements over sh for both programming and interactive use. In addition, most sh scripts can be run by Bash without modification.

And a UNIX shell is... http://en.wikipedia.org/wiki/Unix_shell

A Unix shell is a command-line interpreter or shell that provides a traditional user interface for the Unix operating system and for Unix-like systems. Users direct the operation of the computer by entering commands as text for a command line interpreter to execute, or by creating text scripts of one or more such commands. Users typically interact with a Unix shell using a terminal emulator, however, direct operation via serial hardware connections, or networking session, are common for server systems.

fedorqui
  • 275,237
  • 103
  • 548
  • 598
  • 6
    So bash is a language - but it is also a shell.. ? This is confusing, isn't it? – boop Feb 24 '15 at 10:53
  • 13
    @Brettetete you can also start Python in interactive mode and it behaves like a shell. Or JavaScript, or Ruby or any script language. – Sascha Wolf Feb 24 '15 at 10:53
  • 3
    @Zeeker ohhhh... the penny has dropped. That makes a lot of sense – boop Feb 24 '15 at 10:55
  • 3
    @Brettetete regarding your final goal, I would definitely write "bash" in your cv. I do it, also with "awk". – fedorqui Feb 24 '15 at 11:00
  • 2
    The bit you left off the first quote (emphasis mine): "It offers functional improvements over sh for both *programming* and interactive use." – Paul Evans Feb 24 '15 at 11:05
  • @PaulEvans you are right. I amended my answer with a broad view after reading more stuff. So it is indeed a programming language with which we interact with the OS. – fedorqui Feb 24 '15 at 11:08
  • @fedorqui'SOstopharming' I've posted [my answer](https://stackoverflow.com/a/67498861/1765658), where I give my opinion about `command == programming`... – F. Hauri - Give Up GitHub May 12 '21 at 07:31
29

Bash most certainly is a programming language, one that specialises in the unix/linux shell scripting. It's turing complete so you could (theoretically) write any program in Bash.

Asclepius
  • 57,944
  • 17
  • 167
  • 143
Paul Evans
  • 27,315
  • 3
  • 37
  • 54
  • 2
    Agreed - it is all semantics that resolve around how you define programming language. Does it have specializes syntax, data handling/structures, test constructs, I/O routines, etc... – David C. Rankin Feb 24 '15 at 10:57
  • 2
    Qualified in the "it is all semantics that resolve around how you define programming language" Yes it is a shell, but associated with that shell is a set of rules and syntax that allow you to interact with the shell. `man bash` contains most. So, yes it is a shell, and yes it is a programming language designed to allow interaction with that shell. – David C. Rankin Feb 24 '15 at 11:00
  • @DavidC.Rankin So if i write a simple program in C(which allows you to write loops/ifthens,write to files and store variables) then it is a programming language ? –  Feb 24 '15 at 11:25
  • 6
    It's not worth this perfunctory level of debate. The question was will I get in trouble listing BASH as a programming language skill on a job application. If the employer wants to delve into the semantics that's fine, but I don't think any employer could ding you for listing it. In answer to your comment - sure -- how do you think all the c-like languages began. – David C. Rankin Feb 24 '15 at 11:32
  • 2
    It's also not that hard to write proper "programs" in bash. Kubernetes and git both use large amounts of bash for example. I personally have solved regular whiteboarding problems in bash as welll.. – CoffeeTableEspresso Jan 24 '20 at 23:19
14

There is no perfect definition of what a programming language really is but you can say that every language that is Turing-complete is a programming language in the sense of that every thinkable program can theoretically be written in it (even if it may be awkward to do so and even if it would be horribly slow to run). And Bash is Turing-complete, so there is nothing that could not be programmed in Bash.

The problem with Bash, shells in general is, that it lacks a lot of base functionality, thus when writing scripts for them, you often in fact call external programs to perform the desired work. But that's only taking a shortcut. E.g. if you'd need floating point functionality in a shell, you could actually implement it. It would be possible to write a full IEEE 754 standard implementation in everything that is Turing-complete. In practice such an implementation would be huge, require tons of memory and be horribly slow, so one better calls bc for that. But even implementing bc entirely in bash would be possible.

Here's a bash script I've once written that draws a Mandelbrot set to console. You better be prepared to get some cups of coffee if you want to see the final result, it's going to be a very long night:

#!/bin/bash

BAILOUT=16
MAX_ITERATIONS=1000

function iterate {
    # $1 is x
    # $2 is y
    local zi=0
    local zr=0
    local i=0

    local cr
    cr=$(printf "%s\n" "scale=16; $2 - 0.5" | bc)

    while true
    do
        local temp
        local zr2
        local zi2
        i=$((i + 1))
        zr2=$(printf "%s\n" "scale=16; ($zr * $zr) - ($zi * $zi) + $cr" | bc)
        zi2=$(printf "%s\n" "scale=16; (($zr * $zi) * 2) + $1" | bc)
        temp=$(printf "%s\n" "(($zi * $zi) + ($zr * $zr)) > $BAILOUT" | bc)

        if ((temp == 1))
        then
            return "$i"
        fi

        if ((i > MAX_ITERATIONS))
        then
            return 0
        fi

        zr="$zr2"
        zi="$zi2"
    done
}

function mandelbrot {
    local y
    for ((y = -39; y < 39; y++))
    do
        printf "\n"
        local x
        for ((x = -39; x < 39; x++))
        do
            local xi
            local yi
            local ires
            xi=$(printf "%s\n" "scale=16; $x / 40.0" | bc)
            yi=$(printf "%s\n" "scale=16; $y / 40.0" | bc)
            iterate "$xi" "$yi"
            ires=$?

            if ((ires == 0))
            then
                printf "*"
            else
                printf " "
            fi
        done
    done
    printf "\n"
}

mandelbrot

For those who cannot wait that long, the result should look like this:

                                       *                                      
                                       *                                      
                                       *                                      
                                       *                                      
                                       *                                      
                                      ***                                     
                                     *****                                    
                                     *****                                    
                                      ***                                     
                                       *                                      
                                   *********                                  
                                 *************                                
                                ***************                               
                             *********************                            
                             *********************                            
                              *******************                             
                              *******************                             
                              *******************                             
                              *******************                             
                            ***********************                           
                              *******************                             
                              *******************                             
                             *********************                            
                              *******************                             
                              *******************                             
                               *****************                              
                                ***************                               
                                 *************                                
                                   *********                                  
                                       *                                      
                                ***************                               
                            ***********************                           
                         * ************************* *                        
                         *****************************                        
                      * ******************************* *                     
                       *********************************                      
                      ***********************************                     
                    ***************************************                   
               *** ***************************************** ***              
               *************************************************              
                ***********************************************               
                 *********************************************                
                 *********************************************                
                ***********************************************               
                ***********************************************               
              ***************************************************             
               *************************************************              
               *************************************************              
              ***************************************************             
              ***************************************************             
         *    ***************************************************    *        
       *****  ***************************************************  *****      
       ****** *************************************************** ******      
      ******* *************************************************** *******     
    ***********************************************************************   
    ********* *************************************************** *********   
       ****** *************************************************** ******      
       *****  ***************************************************  *****      
              ***************************************************             
              ***************************************************             
              ***************************************************             
              ***************************************************             
               *************************************************              
               *************************************************              
              ***************************************************             
                ***********************************************               
                ***********************************************               
                  *******************************************                 
                   *****************************************                  
                 *********************************************                
                **** ****************** ****************** ****               
                 ***  ****************   ****************  ***                
                  *    **************     **************    *                 
                         ***********       ***********                        
                         **  *****           *****  **                        
                          *   *                 *   *      

It shall resemble this kind of thing turned by 90 degree (and a bit squeezed):

Mandelbrot set

Robert
  • 33,429
  • 8
  • 90
  • 94
Mecki
  • 125,244
  • 33
  • 244
  • 253
  • 2
    From 1 night to less than 10'! Avoiding *forks*, running `bc` as background subtask... Try [my modified version of bash mandelbrot](https://f-hauri.ch/vrac/mandelbrot_backgndBc.sh.txt) (Still ugly, but quicker! ;-) – F. Hauri - Give Up GitHub Apr 07 '21 at 07:45
  • @F.Hauri Very clever optimization but doesn't work on macOS. Fails with `line 13: syntax error near unexpected token `<'`. Note that macOS only ships 3.2.57 and never will ship bash 4 as the licensing was changed. – Mecki Apr 07 '21 at 14:39
  • 2
    Ok, there is [a modified version tested under MacOS and bash 3.2.57](https://f-hauri.ch/vrac/mandelbrot_backgndBc_4macOs.sh.txt) (Execution time: 8m33.022s) – F. Hauri - Give Up GitHub Apr 08 '21 at 17:42
  • 1
    @F.Hauri No need for bashisms here. A POSIX shell version is even slightly faster [POSIX/shell Mandelbrot @ Gist-GitHub](https://gist.github.com/leagris/59e1b7e72462024b278652696f375e71) – Léa Gris Apr 08 '21 at 23:18
  • @LéaGris You're right about bashism, but the way you address fifos is something wrong. you could gain some seconds by using `<&9` in your code. Try: [mandelbrot_posix.sh](https://f-hauri.ch/vrac/mandelbrot_posix.sh.txt) – F. Hauri - Give Up GitHub Apr 09 '21 at 05:54
  • @F.Hauri updated the Gist with your fixes and made it more visually appealing with a shade of grey and some optimizations – Léa Gris Apr 09 '21 at 12:21
  • @LéaGris forks to `tput` could be limited too! see [my answer about tput setaf...](https://unix.stackexchange.com/a/521120/27653) – F. Hauri - Give Up GitHub Apr 09 '21 at 14:14
  • 2
    @LéaGris One of the advantage using bc as background is: you could define and use function in bc! Now [my new version](https://f-hauri.ch/vrac/mandelbrot_posix-func2bc.sh.txt) make the job in less than 10 seconds!! – F. Hauri - Give Up GitHub Apr 09 '21 at 15:17
  • 1
    @F.Hauri could not stream tput with POSIX shell but used your bc function and now render same orientation and colour gradient as reference picture above https://i.stack.imgur.com/qY17L.jpg – Léa Gris Apr 09 '21 at 23:56
  • @LéaGris regarding all this, I've posted [my answer](https://stackoverflow.com/a/67498861/1765658), where you've been cited – F. Hauri - Give Up GitHub May 12 '21 at 07:29
  • @LéaGris, Posted today a [bash script for parsing log files against time stamp](https://stackoverflow.com/a/41831934/1765658) working as a *super-language*. Feel free to build a POSIX version! (If not quicker, they will be more portable!) – F. Hauri - Give Up GitHub Feb 19 '23 at 16:29
6

My two cents

Coming to this SO question somewhat late, reading fedorqui's answer, I think "programming language" is not exactly same thing as "command language", meaning a language intended to run commands.

About Turing consideration, yes, you could... I personally wrote a lot of libraries around (around monitoring, backups, sysadmin, networking, etc.), but clearly for writing a program, you have to use a real programming language.

However

is a shell (like and others )! Meaning an overall aggregator language, or a super language.

First goal is to be an interactive command processor, in order to use and maintain systems.

One of its first applications was to create s in order to prepare an environment for running programs written in other languages.

So this command processor is ideal for systems, filesystems, networks and a lot of administration tasks, because it's interactive and using its history makes the job of creating scripts just easy.

Its real power

As this language is intended to deal with s, s, s and because said everything is a file, a script could normally deal with everything, directly or by using other tools/binaries/applications. This language is intended to create condition, execution groups and interaction around everything.

This could open a lot of interactivity between systems, networks, iot, etc...

A script could for example (see further my shell connector demo).

1. Open DB, SSH connection and log file simultaneously as file descriptors.
2. Create SQL (temporary or not) table
3. Doing loops, checking for events on DB, SSH connections or other things...
4. Interact with DB and/or SSH...
5. Close all file descriptors (DB, SSH, log file, etc)

Mandelbrot sample:

Comments on Mecki's answer show a good sample of how could be used to deal with other binaries (bc for Mandelbrot)...

Where is used to run bc and aggregate its answers.

  • If a script does one fork for each calculation, this script will take many hours to draw a Mandelbrot on an 80 column terminal.
  • 1st improvement: running only one background fork to bc -l to submit all calculations drops execution time down to 8 minutes.
  • 2nd improvement: passing iterate loop (up to 2000 tests) to bc, drops execution time down to 8 seconds.
  • 3nd improvement: creating more background bc for computing many dots simultaneously (), in order to use multi-core, dividing execution time approximately by available cores... (Thanks to Léa Gris for contributing, helping making this compatible, multi-core idea and adding colors, making this near beautiful, I can't resist to post their result) Colored Mandelbrot in terminal

More examples

I wrote some scripts showing this powerful parallelization capabilities:

  • grepLogByDate Where parsing log file against time stamp could become up to 3 time quicker using (with at least 5 forks to sed, date, bc and paste), than using .
  • multiping.sh will run many ping simultaneously and draw a dynamic graphic using gnuplot, while staying interactive.
  • shell_connector.sh is a library if sourced but contain a full demo using sqlite, date and bc as background co-process if run.
  • getSo.sh is a script intented to connect on SO server, by using with authentication, cookies and Connection: keep-alive.

In order to do some monitoring, checks against differences or so one, we could create a script to open many simultaneous connections to many differents targets, using one of netcat, sql-client, ftp, open-ssl s_client, ssh or else...

... with the ability of running sha1sum, grep, xmlint or bc (if not already backgrounded) when required, while connections stays open...

Conclusion

is a super-language, useful to aggregate a complex application using many programs in various languages.

beaker
  • 16,331
  • 3
  • 32
  • 49
F. Hauri - Give Up GitHub
  • 64,122
  • 17
  • 116
  • 137
  • Impressive to see that you edit your answers many years after you posted them. – kvantour Jun 24 '21 at 21:16
  • @kvantour I posted this answer first on `May 12 2021`. But you're right: I just edited rewritten [this answer to *How to test if a variable is a number*](https://stackoverflow.com/a/61835747/1765658) I've posted more than one year ago. – F. Hauri - Give Up GitHub Jun 25 '21 at 09:52
  • Ah, I misread the date, I thought it was May 2012 ;-) (3yrs before the actual question appeared) – kvantour Jun 25 '21 at 10:07