Makefiles and a bonus.

make(s)

Yesterday I told you that today I'll be teaching you how to make a sandwich. This is not really what I meant. What I meant is "Learn how to use make to build modular scripts".
Imagine this:

  • You have a script that runs rsync to backup your Documents folder.
  • You run rsync locally and then you want to upload the folder to a FTP server.
  • You don't want to upload the files in that folder to the server immediately after uploading them to your backup drive, or you aren't connected to the Internet all the time and running the script will generate a harmless error, but you don't want to redirect the output to that command, etc.

You can't call functions from a script, independently. For example, myscript.sh myfunction() won't work. You can use arguments in that script to trigger a specific function ( like myscript.sh upload_locally ) but IMHO it's a pain in the butt for 2 simple lines.
I think using a Makefile and make command is the simplest, fastest way to do it. Let's find out how to write a Makefile in the lines below.

Makefile

upload_locally:
    rsync command for local backup goes here

upload_ftp:
    rsync command for FTP backup goes here

Broken down you practically construct 2 "functions" (upload_locally and upload_ftp) that when called via make upload_locally for example, they run the command(s) that are after ":". That's four lines. And this is it. That's the Makefile.

Yes, you can make the same thing in a shell script, but how many lines are there in it? Let's "port" the Makefile: myscript.sh

function upload_locally() { rsync command for local backup goes here; }
function upload_ftp() { rsync command for FTP backup goes here; }
$@

Three lines. One less, but far more things to write. And posibly complicated. (Note that #!/bin/bash can be omitted) But can you run it independently? Yes. You can. Though, can you run it altogether? (Like myscript arg1 arg2) Nope. You can't. (Actually you can, but implementing this for 2 lines, without another function it isn't worth it, trust me.)

function testA(){ echo "Test A"; }
function testB(){ echo "Test B"; }

$@
myscript testA testB
Test A

Running make arg1 arg2 will run the 2 "functions" named arg1 and arg2 inside the Makefile.

Now let's go a little further:

Makefile

all: upload\_locally upload\_ftp

upload_locally:
    rsync command for local backup goes here

upload_ftp:
    rsync command for FTP backup goes here

Running make all will run upload_locally and upload_ftp.

And let's do the same with myscript. myscript

function testA(){ echo "Test A"; }
function testB(){ echo "Test B"; }
function all() { testA(); testB();}
$@

Condensed and amateurish, the file myscript has 4 lines. Without #!/bin/bash.
Running myscript all will call the functions testA and testB.
The file Makefile is written correctly from a syntax, indentation and style point of view. Let's write the bash script in a more readable way and let's use a (more) correct style for it.

myscript

#!/bin/env bash
function testA()
{ 
    echo "Test A";
}

function testB()
{ 
    echo "Test B";
}

function all() 
{ 
    testA(); testB();
}

$@

I think it isn't worth it using a script with 3 functions when you can use a Makefile.
Oh, have you noticed how I didn't use the word function for Makefiles? That's because the functions are named "rules" in Makefiles. You are writing a Makefile with rules for make command to execute.

Now the bonus.

A friend told me that he has a site written entirely in bash. You can visit it here. It's a site that automatically writes jokes on a image and publishes them to his site. The jokes are taken from another site, but I still find it nice.
Below you can find a script that he wrote:

youtube-dl -o "%(title)s.%(ext)s" --extract-audio --audio-format=mp3

for i in *.mp3 ; do ffmpeg -i "$i" -ac 2 -ab 64k -ar 44100 "conv_$i"; done

He also said that he has a lot of other scripts but wanted me to post this specific one here. It's more a wrapper for a program called youtube-dl.
It uses ffmpeg and what it does is converting a mp3 file downloaded from YouTube to a lo-fi version of it. In case that you don't care about quality or you don't have much space left on your audio player, this can be useful.
Don't use it on your mp3 files from your PC unless you want quality loss!
You have been warned!

PS: I've uploaded a 3D LEGO model on Images page. Check it out!

Comments !

blogroll

social