*Wednesday, 1st July 2026 - 13:10 UTC+01:00* # Basic Functions in Bash Functions are known amongst multiple coding language for being something that is reusable and for allowing neat and compartmentalised (modular) code. They also aid in sharing code, as you will only need to know which inputs and outputs to use. A Bash function will have the following syntax: ```bash function_name () { #function_code return #something } ``` When naming the function, which will be used to call it later, make sure it is a sensible one that relates to what it does. Also make sure to add open and close parentheses after the function name.<br> Add the code inside the curly brackers. Anything can be used, including a shell-witin-a-shell. A function can also be creted in the following manner: ```bash function function_name { #function_code return #something } ``` The main difference in this type of function structure is that the word function is used to denote starting a function build, and the parentheses on the opening line can be dropped, though most people tend to keep them in. Calling a Bash function is as simple as writing the name. ```bash function print_hello () { echo "Hello world!" } ``` ``` Hello world! ``` > [!example] **Example**: Fehrenheit to Celcius Bash function > >As an example, a function could be written to convert from Fahrenheit to Celcius. > > ```bash > temp_f=30 > function convert_temp () { > temp_c=$(echo "scale=2; ($temp_f - 32) * 5 / 9" | bc) > echo $temp_c >} > convert_temp # Call the function. >``` >``` >-1.11 >``` ## Example - Uploading Model Results to the Cloud One example of how a function could be used is to upload model results to the cloud. In this example, a for loop is being used inside a function. This kind of function is one that data scientists and anyone working with logs would find useful. In this examplem, it will execute the function, which loops through the for loop and says `Uploading $file to cloud` for every file that is the output of `output_dir/*results*`: ```bash # The function is created function upload_to_cloud () { # The files are looped through using a glob expansion for file in output_dir/*results* do # Echoes that the files are being uploaded echo "Uploading $file to cloud" done } # The function is called. upload_to_cloud ``` ## Example - Days of the Week ```bash # Create function what_day_is_it () { # Parse the results of date current_day=$(date | cut -d " " -f1) # Echo the result echo $current_day } # Call the function what_day_is_it ``` ``` Wed ``` # Arguments, return values, and scope Passing arguments into functions is similar to how arguments are passed into scripts, as the `$1` notation is used in both. > [!note]+ Refresher > Like with dealing with passing arguments into scripts, the following `ARGV` properties are accessible: > > - Each argument can be accessed via the `${num}` notation. > - `$@` and `$*` give all the arguments in `ARGV` > - `$#` gives the length (the number) of arguments. File names are one of the many things that can be passed into functions as arguments: ```bash function print_filename { echo "The first file was $1" for file in $@ do echo "This file has name $file" done } print_filename "LOTR.txt" "mod.txt" "A.py" "additional_pylon.s" ``` ``` The first file was LOTR.txt This file has name LOTR.txt This file has name mod.txt This file has name A.py This file has name additional_pylon.s ``` In programming, the **scope** refers to how accessible a variable is. - **Global** means that something is accssible anywhere within the program, including inside FOR loops, IF statements, functions, and more. - **Local** means something is only accessible only within a certain part of the program. This matters because if you try to access something that only has a local scope, the program may fail with an error. In Bash, unlike most programming languages, all variables are global *by default*. ```bash function print_filename { first_filename=$1 } print_filename "LOTR.txt" "model.txt" echo $first_filename ``` ``` LOTR.txt ``` ## Scope in programming A global scope may be dangerous due to there being a higher risk of something unintentional happening.<br> The `local` keyword can be used to restrict the variable of a scope. ```bash function print_filename { local first_filename=$1 } print_filename "LOTR.txt" "model.txt" echo $first_filename ``` ``` ``` ## Return values But what if you are trying to get argoumts out of a function? The `return` option in Bash is only meant to determine of the function was a success (`0`) or failure (other values `1`-`255`). It is captured in the global variable `$?`. This presents two options: - Assign to a global variable. - `echo` what we want back (such as the last line in a function) and capture it using shell-within-a-shell. ```bash function function_2 { echlo # An error of 'echo' } function_2 # Call the function echo $? # Print the return value ``` ``` script.sh: line 2: echlo: command not found 127 ``` What happened is that there was an error when the function was called. The script tried to find the command `echlo` as a program, but it did not exist.<br> The return value in `$?` was 127 (error). WHat if we want to correctly return a value to be used elsewhere in the script? `echo` and a shell-within-a-shell capture will sort that out: ```bash function convert_temp { echo $(echo "scale=2; ($1 -32) * 5 / 9" | bc) } converted=$(convert_temp 30) echo "30 F in Celcius is $converted C" ``` ``` 30 F in Celcius is -1.11 C ``` # Scheduling Scripts with Cron There are many situation in which scheduling a script can be useful: - Regular tasks that need to be done. Maybe they are daily, weekly, or multiple times a day. - Optimal use of resources (running scripts in the early hours of the morning) Scheduling scripts with `cron` is essential to a working knowledge of modern data infrastructures. Cron is driven by the `crontab`, which is a file that contains `cronjobs`, each of which tell `crontab` what code to run and when. To see what schedules (`cronjobs`) are currently programmed, use the following command: `crontab -l` There are 5 stars to set when constructing a cronjob: - Minute (0 - 59) - Hour (0 - 23) - Day of the month (1 - 31) - Month (1 - 12) - Day of the week (0 - 6) (Sunday to Saturday) The default `*` means 'every'. A cronjob is formatted `* * * * * command_to_execute` > [!example]- Cronjob Examples > > `5 1 * * * bash myscript.sh` > > In this example, it is set to execute at 1:05am every day. > > --- > > `15 14 * * 0 bash myscript.sh` > > In this example, it is set to execute at 2:15pm every Sunday. > > --- > > `15,30,45 * * * * bash myscript.sh` > > In this example, it will run at the 15, 30, and 45 minute marks for whatever hours are specified by the second star.<br> > This type of thing is useful for when you want to run something multiple times a day or every however many time increments. > > --- > > `*/15 * * * * bash myscript.sh` > > In this example, the cronjob will run every 15 minutes. To edit the crontab and add or remote crobjobs, the command `crontab -e` can be used.