Shells have specialized features for working with files and getting data from one program into another (assuming that data is text). For those tasks, shell scripts can be less cumbersome than a scripting language like Python.
Shell scripting also has the advantage that the commands you use are basically the same commands you'd use from the command line -- so if you can do something in the shell, you're more than halfway to scripting the same operation.
Here for example is a bash script that moves all the PNG files from the current directory to a specified directory.
mv *.png $1
Here's a Python version.
import sys, shutil, glob
for filename in glob.iglob("./*.png"):
- The bash script is a third as long as the Python if you count lines (excluding the shebang line) -- even less by character count
- The Python script requires three libraries to be imported, while everything you need for this task is natively available in bash
- The Python script requires an explicit loop to move the files, whereas that is part of the semantics of the
mv command in bash
- The bash script can run faster -- you'll probably invoke it from bash, and you can use
source to run it in the same instance of the shell
glob.iglob("./*.png") is quite a mouthful just to say
If you wanted to write a basic pipe operation in Python, you would be astounded at the verbosity. (Of course, some things, like piping through
grep, can be replaced by Python code rather than using an external program, so you often don't need to pipe quite as much.)
As a counterexample, I once had to write a routine that checked to see how long each of the filenames were in a particular directory. If they were longer than supported by a particular OS, they had to be shortened. This could result in duplicate filenames, which I needed to rectify, and since they would be linked from a Web page, the shortened names needed to be stable, i.e., they should be generated in such way that the same long filename would always result in the same shortened filename. I did this by generating a hex md5 of the long filename and appending the first four characters of that to the shortened name (names could still collide, but it was very unilkely, so I just checked for that condition and bailed if it should happen). It also had to record the rename operation so a batch search-and-replace could later be done on the files to fix the links between them (I wrote out a sed command file and passed that to sed for each file).
I did this in bash because it was part of our build system which was already written in bash. It was exactly as hard to get right as you are probably thinking. It would have taken a lot less time to write in Python and probably would have been clearer, too.
In short: different languages are designed for different kinds of tasks; choose the language available to you that is best suited to the task at hand.