Shell Scripting: learn the foundations in an hour

Lo shell scripting is an essential skill for any person who uses the so-called 'Command Line Interface' (CLI), let's look at it specifically.

Shell, terminal ... are they two things the same?

No, they are two different things:

  • Il terminal: recalls the textual shell in a graphic interface program, with visual settings (background of the emulator, color of the output characters (and their font), name of the window, etc ...), allows to execute commands in it, 'inside a graphical environment. Without a shell emulator we should call the tty with the corresponding combination [usually Alt + Shift + Fx (where x = 1,2,3,4)], so we should exit the graphical interface and 'go' in text mode; inconvenient, no?
    The terminal sessions are called pts, and go from 0 to n-1 (where n is the last terminal open, so if I have 3 open terminals will be identified with 0,1,2).
    Specifically, with pts / 0 the first is indicated, with pts / 1 the second and so on ... While the tty are the virtual consoles or the emulation of the shell in text mode. They are identified with tty / 0, tty / 1, etc ...
  • La Shell: the command interpreter that is entered after the prompt (see bottom for more info). It is essential as it allows direct communication with the kernel. These are the shells used in Unix:
    • Sh: the first Unix shell able to interpret commands, still present in all Unix systems (GNU, BSD, etc ...).
    • csh: shell compatible with Sh, syntax C like
    • GNU Bash: (Bourne Again SHell), advanced shell, the "reborn" of Sh (Bourne AGAIN), used in all GNU systems as the default shell
    • Z Shell: the most advanced shell, has many advanced features and is very similar to Bash, it is also compatible with the latter script. It has an interface that allows you to configure the shell for the first time in a simple way, themes of all kinds, right prompt. Yes, it is similar with Bash, but (for example) the character sequences (metacharacters) that refer to certain information are different.

img_shell_1

To change the default login shell:

chsh -s $ LATUASHELLPREFERITA

You can use one shell in another, as a child process of the first shell process,

bash-4.3 $ sh
sh-4.3 $ echo "I'm in sh!"

... and return to the default shell

sh-4.3 $ exit
Is it important to choose my default shell?

My answer is yes, the shells that I recommend are obviously Bash and Z Shell, if you don't make it hot or cold to modify the various configuration files, introduce additional functions such as syntax highlighting, advanced auto-completion, stay on Bash, otherwise Z Shell is the best choice.

So if I download a script that declares the / bin / sh interpreter and I'm using / bin / zsh can't I use the script?

Yes, you can easily use the script because when the script is executed, / bin / sh is first executed, declared as an interpreter at the first line of the script (#! $ INTERPRETE), then the instructions are executed interpreting them one-to-one from / bin / sh

Shell scripting ... what is this?

We implement shell scripting whenever we execute a command, even implementing simple commands like ...

echo "Hello"

or

su -c "cp $ FILE /"

So when you encounter those files with extension * sh you are executing commands, more elaborate, with certain conditions, in a very specific order. Although it is possible to verify a condition with if even from a terminal, the disadvantage is that you have to write everything on a line ... so you won't understand a bat ...

It is a good habit to leave the code in good condition, and at least require that the code is well indented (see below for more info), well commented and that it does not contain any syntax errors; otherwise the interpreter alerts as soon as it meets that particular instruction. However it is possible for example to use different options than those we want, (this depends on the program, which is called by the interpreter based on the variable $ PATH) this option is right, the only problem is that it does not perform what we have asked, and this could lead to serious consequences.

*THE'interpret: a program that reads the instructions at the time of execution, the program cannot be compiled. (Python, Bash, Sh, etc ...)

Is it important to learn Shell Scripting?

Yes, as well as knowing how to handle the operating system well, it is also useful to have a first idea of ​​how a programming language like Python works (C / C ++, Java is too much ...), even if the syntax between the two is different.

The main advantage?

Perform complex operations quickly. And flexibility.

Each shell has its own configuration file, they are created as soon as the shell is loaded the first time the new OS is started. If not, you can create these files yourself. The most significant file, where users enter more customizations is

for Bash:

$ HOME / .bashrc 

for ZSh:

$ HOME / .zshrc

In these files functions, aliases, etc ... are defined. They must be loaded at the start of a new terminal (pts / x), these files can be found on the internet, for example you can change the default prompt with a customized one : in Bash it is sufficient to modify the variable PS1, in ZSh we can modify the left and right prompt respectively the variables: PROMPT and RPROMPT, PS1 has different metacharacters with respect to PROMPT and RPROMPT. Metacharacters can be found for each shell by searching on Google or any other search engine.

What is the prompt?
The prompt is that line that tells us which users we are, our hostname, where we are, and waits for an input command.

These are metacharacters:
[u h, etc ... <= Bash, Sh] [% h,% u,% d,% l,% ?, etc ... <= ZSh]

But what is a metacharacter?
It is a string that refers to another string, number or character, for example:
u: stefanozzz123, ie: the "u" metacharacter refers to the string stefanozzz123 which would be my username.
%? : 0, that is: the metacharacter "%?" refers to the 0 number which would be the return code of the program just ended.

Before starting:

  • Environment variables: [export VAR = "content"] if you pass from one shell to another these variables do not change. It is possible to display them all with the command (an environment variable can be $ USER, $ SHELL ...) [env]
  • Shell-Built-In programs: programs integrated in the shell, can be pwd, exit, export ... for more info: GNU Bash Builtins
  • How to make a script bootable: simple, there is chmod (CHange MODe), a handy utility that allows you to change the permissions of a file, in our case chmod + x script.sh it is enough to add the parameter x to the file properties, to make it executable, but with chmod it is also possible to remove the permissions (chmod -x script.sh) and also other operations ... Chmod is useful if you declare the interpreter (see the first script), otherwise you need to call sh and pass the file as an argument (sh script.sh)


Let's take a small script to get started

Interpreter, comments, assignment, variable declaration, input / output, return codes, arithmetic operations

We enable execution permissions with the following command:

chmod + x script_name.sh # enable execute permissions

Otherwise:

sh script_name.sh # is passed directly to the interpreter
#! / bin / sh #Assign USER the value of the variable $ USER (demonstration purpose) USER = $ USER #Show in stdout and request input in stdin, without going to head echo "Hello USER" echo -n "Enter the first number : "read N echo -n" Enter the second number: "read X #Show the product echo" The product between $ N and $ X is: $ (($ N * $ X)) "#Exit with return code 0 (true) exit 

Analyzing this script:

  • the interpreter used is / bin / sh which is included in all UNIX and Unix-like systems
  • There are comments to specify what a particular instruction is for
  • We have declared and initialized USER at the same value as $ USER
  • with echo, the greeting with the USER variable preceded by the dollar is shown in stdout ($)
  • We then executed echo all the same but with the n option which allows us to prevent the text shown from wrapping to let the user enter values ​​after stdin
  • We performed echo to show in stdout that the product between $ N and $ X is the product between the two values ​​stored in variable $ N and $ X
  • Everything went well, exit with 0 return code

It is optional to declare the interpreter, but a good habit in my opinion!
We can see how the variable is declared, it is a very important thing because if you start a variable like this:

*Note: Interpreter - program that reads the instructions of another program at the moment (Python for example), the opposite of Compilation in a few words, even if there are hybrid languages ​​Compilation-Interpretation (Java)
*Note: Compilation - Process in which the code of a program is translated into machine language, ready to be "chewed" by the processor. This process takes place through a Compiler (GCC, G ++ for example). So it is no longer readable to the human eye, bytecode = binary (not those of the train), a series of 0 and 1 that signify certain operations, with the reverse engineering technique it is possible to trace the functioning of those 010101011010.

VAR = "hello"

that's right, but if you start it this way:

VAR = "hello" VAR = "hello" VAR = "hello"

it's wrong.
A variable therefore declares itself in this way:

VARIABLE_NAME = VALUE

Where value can be a number (without quotes), or a string (delimited by double quotes), a single character (delimited by a single quote), or another variable.
To reuse the variable it is necessary to 'prefix' the symbol of the $ (dollar), be careful not to put it before during the initialization phase.

echo "$ VAR $ USER" $ ~> good morning ste

In the case of stdin, the read program is used

$ read # wait until the user presses enter $ read VAR #sets in VAR (which is declared when writing the value) the value that is entered in stdin

it is possible to reuse the value of VAR in the same way, as for the other variables.

Finally, to perform arithmetic operations, you can use the following command:

echo $ ((1 * 2)) #product between 1 and 2

the operators are:
*: multiplication
-: subtraction
+: addition
/: division

respect the spaces as in the example or sh will punish you. 🙂
Ah, you can execute commands inside echo or in a variable

 
echo "Your current kernel is $ (uname -s -r)" #Or CURRENT_KERNEL = $ (uname -s -r)

We will explain Stdin, Stdout, Stderr, redirection of the output below 😉


Standard Output / Error / Input; Output Redirection

 
#! / bin / sh #Standard Output [stdout] echo "Hello World!" #Print the string "Hello World" in the standard output channel #Standard Error [stderr]> & 2 echo "Error!" #Print the string "Error!" in the error channel of the output #Standard Input [stdin] echo -n "Write your greeting here:"; read SALUTO #Print the request in stdout, then wait for the user to send it and store the text written in $ SALUTO echo $ SALUTO # $ SALUTO is shown in stdout;) #direction output to file FILE = $ HOME / provaredirection echo "Here is my greeting: $ GREETINGS"> $ FILE #irrede the text in $ FILE, in this case DELETE ALL the echo file "Here is my equal greeting: $ SALUTO" >> $ FILE #redirige text in $ FILE , in the case seen now, the string is positioned at the last line of the file! #echo "This string will not be shown on file, and its contents will be deleted" 2> $ FILE #redirige on $ FILE the string (error), but the contents of the file will be deleted;) 

There are two ways to print text on screen, or rather two channels:

  • Standard Output [stdout]: plain text
  • Standard Error [stderr]: channel used to print errors, usually used when a program returns value> = 1

Instead to request something in input (string, number, character) there is the channel of Standard Input, simply with the read statement.
But be careful, if you only use the read statement you use the code simply to wait for a send, no data will be allocated in any portion of memory!

read NUMBER

instead, then a number in $ NUMBER, which we can then reuse.
Redirection is useful for example when we have a large configuration file and we need to do things as quickly as possible, so with the >> operator (which is different from>) we can avoid deleting the whole file and sending 'the string after echo in that particular file.

echo "stefanozzz123 ALL = (ALL) ALL" >> / etc / sudoers

simply, the text is not shown in stdout but is delivered to / etc / sudoers
the> operator works in the same way only that it overwrites the file so if I execute it

echo "stefanozzz123 ALL = (ALL) ALL> / etc / sudoers

my sudoers file will be deleted 😉 always be careful when using this operator.


Operators (&&) (||) (;) (|) ([[-f $ FILE]]) ([[-d $ DIRECTORY) (&) ->

#! / bin / sh #Se clear has 0 return code, then run [...] clear && echo "The terminal has been cleaned from the old output." # if clr has return code 0 then execute ls, otherwise print to error channel [...] clr && ls || > & 2 echo "It was not possible to clean it up!" #If clear returns both 0 and 1 + return code execute anyway ls clear; ls ## pipe operator (|) ## #In a few words # kernel messages are passed to grep, which looks for the expression "ath9k" dmesg | grep ath9k #then with pipe it is possible to pass the output of one file to another to perform any operation on it. other example? cat / etc / sudoers | grep root # the output of / etc / sudoers (generated by cat) is transferred to grep which looks for the expression "root" touch random echo b> random echo a >> random cat random | sort # quick checks ## [[-f $ HOME / fileExists]] && echo "$ HOME / fileExists :: exists" || echo "That file does not exist!" [[-d $ HOME]] && echo "your home directory exists!" || echo "Does not exist :(" ## process father and child ## dmesg & lspci # together with dmesg runs lspci, the child process of dmesg

I wanted to clarify the use of &&:
it is not wrong to use &&, but be aware that the operation you request will only be performed and if the program return code will be 0, if you want to run a program first and then the other regardless of the return code, simply use the operator ; ([Command]; [comando1]), if you want a program to perform a certain operation after the first program that has return code> = 1 you must use the || operator ([Command] || [comando1]).

  • Return code 0: the program has ended successfully, no errors.
  • Return code > = 1: the program had problems, something went wrong!

The pipe operator ( | ) allows us to use the output of one program in another program. The most trivial example:

cat file | grep foo

The output of the cat command is shown partially if the grep program finds the expression foo, if it finds nothing ... no output! It's a bit like redirection but you can do more useful operations like this.
The sort command is used to re-order a file in alphabetical order, basically it does not change it, it only shows the changes in stdout and that's it, nothing more. In the example I created the file "random", redirected bea (so the content of the file is:)

~ $> cat random ============== b a

therefore they are not in alphabetical order; with sort we can temporarily rearrange them, but there is an option to edit the file.

 
~ $> cat random | sort =============== a b

.
Last but not least the operator &, which allows us to run a child process from a parent process, here is my example

echo hello & echo hello

[dmesg -> lspci (the sequence IT SHOULD be this; father The programs are run from right to left, the reason I never honestly understood: /

Check conditions, use iterations

#! / bin / sh #Condition, check condition to be true if [[$ USER == "root"]]; then echo "You are the root user!" # if the condition presented above is false, try again with this: elif [[$ USER == "stefanozz123"]]; then echo "It's you!" # if both are false ... else echo "You are any other deadly user, $ USER" fi #Case: similar to if # verify that these values ​​are present in $ 1 case $ 1 in #If you typed 1 (1) echo "You wrote 1" break ;; #If you typed 2 (2) echo "You wrote 2" break ;; # Anything else (*) echo "You wrote any other number / string: $ 1" break ;; esac #Cycle while: # while [condition is true] execute # operations #fine #if the condition is true then execute this code block until you press CTRL + C while [[$ USER == "root"]]; do echo "It's dangerous to be a root user!" sleep 3 done #For: #for i which is equal to 0, as long as i is less than or equal to 20 add to "2" up to twenty for ((i = 0; i <= 20; i + = 2)) #follow do echo "2 table: $ i" #fine done #a index values ​​are assigned 1,2,3,4,5,6,7 for index in 1 2 3 4 5 6 7 #follow do #for each value in index echo "The following are available in the index values ​​(value): $ index "#fine done

To write elaborate code, more complex instructions, it is necessary to use:

  • If
  • Homes
  • while
  • for

They are instructions that allow you to check conditions in a more elaborate way and perform cycles based on a certain condition. If you have had other scripting / programming experiences you will surely have heard of iterations and conditions.
if

if  condition; then
     operation

fi

This above is the standard syntax, easy to understand, if condition is true, then do it operations.
But with if we can also perform operations if the first condition is false

if  condition; then
     operation
else
     operazione1

fi

The operation is the same as the previous one except that the else condition was included:
se condition it's false, jump operation e run condizione1
Ma we have another chance, let's see the code:

if  condition; then
     operation
elif condizione1; then
     operazione1
else
     operazione2

fi

note the elif, unlike else, it is a mixture of else and if (in C / C ++, Java is written precisely else if ) [in Italian otherwise if], allows us to verify another operation if the first is false, we can implement as many as we want, in the end else but it is always optional.
Finally the if statement closes with the keyword fi (the equivalent of} in Java, C / C ++, JavaScript, and other languages ​​with the C-like syntax).

case statement
it works in a way very similar to if, only that it allows us to save time, usually it is used for fast operations:

case $ 1 in (1) echo "you passed 1" break ;; (2) echo "you passed 2" break ;; (*) echo "you passed $ 1" break ;; esac

This is equivalent to

if [[$ 1 == 1]]; then echo "you passed 1" elif [[$ 1 == 2]]; then echo "you passed 2" else echo "you passed $ 1" fi

So as we can see the case allows us to check conditions quickly,
any type of data identifies itself inside the brackets () (which is string, number, character), then, if the condition occurs, the required operations are performed, at the end the break instruction is launched, necessary to exit the verification process of the houses, each block is terminated with ;; .
It is identical to the C / C ++ switch only that C has a different syntax:

// ... int main (int argc, char * argv []) {// ... switch (argc) {case 1: printf ("You passed 1 argument from the command line"); break; case 2: printf ("You passed 2 arguments from the command line"); break; // ...} // ...

while
the while is a loop that checks if a condition is true or false, if the condition is true, while it is true, it performs certain operations until that particular condition becomes false.

while [[$ USER == "root"]]; do echo "it is dangerous to be a root user!" sleep 3 done

This block verifies that $ USER is equal to the root string to verify that the user who executed the program is, in fact, root, if so, he prints the string in stdout, waits for 3 seconds and rewrites it to infinity, until l user does not change (impossible) or press CTRL + C.

for, for in
The for is also a loop that lets you run 3 operations, but let's look at the for-in first with a quick example:

for index in 1 2 3 do echo index: $ index done

creates a new index variable and stores the 1,2,3 values ​​inside it; then he prints them on screen one by one in the written order. A "species" (between 5 quotes) of arrays (array: variable containing 2 or more homogeneous data, of the same type. An example of an array in shell / bin / sh:

ARR_VAR [1] = "Hello" # inserts in 2 position the string Hello ARR_VAR [2] = "Hello" # insert in the 3 position the string Good morning echo $ {ARR_VAR [*]} #Show all the contents of the array echo $ {ARR_VAR [1]} # Show an array content

Where is the 1 position?
Arrays have values ​​from 0 to n-1 that is, 0 = 1, 1 = 2, 2 = 3. It starts from 0 and goes up to 9 for example, we will have 10 strings in the array ranging from 0 to 10-1). [closed the array bracket]
So, coming back to us, for-in can be useful for many things ...
The classic for, ie the one composed of three instructions is composed as follows:

for ((i = 0; i <= 100; i ++)) do echo "N: $ i" sleep 1 done

it is read:
"For i which is equal to 0; as long as i is less than or equal to 100; add ai the 1 value up to 100 ”
then execute the operation in the do-done block until i is incremented, in our case every time i incurs the increment it will be printed in stdout N: $ i, there will be a second 1 wait and then the same will be re-printed string, it will wait a second and so until 100 ...
Let us dwell on the increase:

  • i ++: verify ie then add 1
  • ++ i: add 1 and then check i
  • i–: check i and subtract 1
  • –I: subtract 1 and verify i
  • i + = 2: add to the 2 value, equivalent to say: i = i + 2 (obviously 2 can be any number) [echo $ ((i = i + 2)); echo $ ((i + = 2))]

The for loop can be useful on many occasions of need, especially for-in.

We have omitted a similar until while, you can look for its operation on Google 🙂
The select: allows you to create menus, you can combine it with both houses and if
This is the select of LinuxCleaner

select YOURCHOICE in 'Show tip' 'OS.Shell' 'Update & check if there are useless packages'' Clean temporary files / tmp '' Clear trash '' Update kernel '' Add repositories' 'Install packages by your package manager' ' Search packages by package manager (from repositories) '' Remove packages by package manager '' Install by PKGBUILD (Arch) 'Install package by file' 'Delete packages by manual tool' 'Installed stock kernels'' Compile kernels' 'Update / Reinstall GRUB configuration file '' About your system '' About Developer '' About Script '' Quit '; do case $ YOURCHOICE in ("Clean temporary files / tmp") if [[$ USER! = "root"]]; then echo "You need to be root" else cleanTemporaryFiles fi ;; ("Clear trash") clearTrash ;; ("Update and check if there are useless packages") if [[$ USER! = "Root"]]; then echo "You need to be root" else checkUpdates fi ;; ('Add repositories') if [[$ USER! = "Root"]]; then echo "You need to be root" else echo "" echo "=============" echo "Which distro are you using / is your distro based on this listed below? "echo" 1) Debian "echo" 2) Red Hat "echo" 3) Arch Linux "echo -n" Choice [1,2,3] -> "read BASEDON echo" ============= "case $ BASEDON in (1) APTREPODIR =" / etc / apt / "if [[-d $ APTREPODIR]]; then makeChoiceDebianBased else echo" Your system doesn't have APT-GET / APT-GET repository folder is not present "echo" ============= "echo" "fi ;; (2) YUMREPODIR =" / etc / yum.repos.d / "if [[-d $ YUMREPODIR]]; then makeChoiceRedHatBased else echo "Your system doesn't have YUM / YUM repository folder is not present" echo "=============" echo "" fi ;; (3) PMREPODIR = / etc / pacman .d / if [[-d $ PMREPODIR]]; then makeChoiceArchLinuxBased else echo "Your system doesn't have PACMAN / PACMAN repository folder is not present" echo "=============" echo "" fi ;; (*) echo "I cannot recognize this option." echo "=============" echo "" ;; esac fi ;; ("Search packages by package manager (from repositories)") searchPackagesByPackageManager ;; ("About Developer") infoAboutDeveloper ;; ("About Script") infoAboutShellscript ;; ("Install packages by your package manager") if [[$ USER == "root"]]; then installPackagesByPackageManager else echo "You need to be root" fi ;; ('Remove packages by package manager') if [[$ USER == "root"]]; then removePackagesByPackageManager else echo "You need to be root" fi ;; ("Install package by file") if [[$ USER == "root"]]; then installPackagesByFile else echo "You need to be root" fi ;; ('Delete packages by manual tool') if [[$ USER == "root"]]; then deletePackagesByManTool else echo "You need to be root" fi ;; ("Compile kernels") if [[$ USER == "root"]]; then echo "Good idea ... Root is not needed for getting / config / compile the kernel "compileKernels else echo" Root user is required for installing kernel modules, (if you want) update the bootloader configuration, (if on Arch) build a ramdisk "compileKernels fi ;; ( "About your system") aboutSystem ;; ("Update kernel") if [[$ USER == "root"]]; then updateKernelByPackageManager else echo "You need to be root" fi ;; ("Show tip") showTip; ; ('Quit') clear echo "[*] Bye bye! "exit 1 ;; ('Update / Reinstall GRUB configuration file') if [[$ USER ==" root "]]; then echo" [+] OK. " updateAndReinstallGRUB else echo "[!] You need to be root." sleep 2 clear main fi ;; ('OS.Shell') runOSCommand ;; ('Installed stock kernels') installedStockKernels ;; ('Install by PKGBUILD (Arch)') if [[$ USER == "root"]]; then echo "[-] MakePKG will not work if you run it with root access" else buildByMakePKG fi ;; (*) echo "Retry, I cannot recognize this option" ;; esac done 

if you run LinuxCleaner you can see that menu created thanks to select and case, if the correspondence is pressed to exit, the exit instruction will be executed and at that point the program ends.
[syntax: select VARIABILE_DA_VERIFICARE in 'opt1' 'opt2' 'opt3'; do Operations with houses or if done. So you need to check the correspondence of $ VARIABILE_DA_VERIFICARE with the three items' opt1 '' opt2 'opt3' which are sorted according to their position. Last curiosity: we can modify the prompt, that is the line that asks the input with the variable PS3; then PS3 = "Select ~~>". Note that the select I tested with sh and bash, with Z Shell the situation should be slightly different, but the concept is always the one 😉].


Functions and function arguments, return code, exit
What is a function?
A function can be defined as a small sub-program that performs specific tasks, it is a block of code that executes certain instructions, the "purpose" of the existence of the function can be identified by the name of the function (sum (); multiplication ( ); doSomething () ...), we will also see the scope better, or the degree of visibility of a variable.
What are function arguments?
are parameters, which are passed to the function through special variables ($ 1, $ 2, $ 3 ...), we'll see what they are for by looking at the code better
What is the return code
the return code is a value that a program returns at the end of its execution, this value is conditioned by various aspects, and based on its value it is determined whether the program has ended correctly, or not. We will see the values ​​better after analyzing the code.

#! / bin / sh diCiao () {echo "Hello"} tell me YourSame () {echo $ 1} sumTwoNumbers () {SUM = $ (($ 1 + $ 2)) echo "Sum between $ 1 and $ 2 = $ SUM" return $ SUM} #Simple, parameters are not passed by Hi # We write a greeting tell meOneHoursHello Hello #We write two addends sumTwo Numbers 5 6 if [[$ SUM == 11]]; then echo "The program ended correctly; return code: 0" exit else echo "There was some error, the program ended with return code> = 1" exit 1 fi

In this script we have 3 functions:
a print in stdout simply "Hello"
the second asks for the parameter $ 1 to print a greeting of your choice
the third performs an operation with the parameters $ 1 and $ 2 passed to the function. Then it returns the value of $ SUM which contains the aforementioned sum.
If we look at the last two functions there is no significant value, only variables that will then be determined by the parameters passed to them. Basically those $ 1, $ 2 are the "preview" of what will happen with the actual values ​​that will replace them, whether they are string data, integers, characters, etc ...
Notice how the functions are declared: function () {ist; ist1}, if you come from C / C ++, Java, JavaScript, Python, ... No ... no variable should be inserted between the brackets. The brackets are used by the interpreter to determine whether that is a function or not. The variables are $ 1, $ 2
and are already established in the code.
When the function is to be called, it is simply called this way:

functionName var1 var2

we do not use round brackets to pass arguments, we pass directly separated by a space, where var1 e var2 correspond to $ 1 and $ 2 respectively
$ 1 = first argument
$ 2 = second argument
$ x = x argument.

Finally, having no ideas for a better example, I verified that $ SUM was equal to 11 (5 + 6), if it had been the same, with the instruction exit the program ends successfully (value: 0), otherwise it would end with 1 value thanks to the instruction exit 1 where precisely, exit is the instruction and 1 is the argument passed to it, exit with a value as a parameter exits the program and returns that certain value to determine if the program has ended successfully.

  • 0: program completed successfully
  • > = 1: problems occurred during execution that led to early closure / CONTROL + C 😀

*I could have determined if $ SUM is equal to 11 just like that

[[$ SUM == 11]] && echo "Program completed successfully" exit || echo "There was an error" exit 1

As for the scope of the variables: the scope as explained above is the degree of visibility of the variables, in this case x is visible in all functions, even $ SUM is visible outside the function. In Python for example, if we are in a function, we can declare a global variable with the keyword overall var_name, otherwise the variable has local scope, that is it is visible only inside the function, or, if declared with the same name it does not assume the same value. In C / C ++ we have to declare a static variable outside the main () to get the result of "variable visible within the same file, but not available outside it.", Otherwise if we want the "variable / function visible throughout the files it is necessary to declare the function with the extern keyword that establishes the global scope in all files. "

Command line arguments with $ 1, $ 2, $ 3 ... $ @
You can pass arguments from the command line using the special variables $ 1, $ 2, $ 3 ... that work the same way as with the functions.
Of a command line program, its execution can be modified with these special variables that store the arguments passed to them.

#! / bin / sh ARG _ = $ 1 ARG_1 = $ 2 ARG_2 = $ 3 if [[$ ARG_ == "--sum"]]; then echo "Find arguments:" for i in $ @ do echo "Parameter: $ i" done echo "Sum: $ (($ ARG_1 + $ ARG_2))" exit elif [[$ ARG_ == "--molt"]]; then echo "Find arguments:" for i in $ @ do echo "Parameter $ i" done echo "Multiplication: $ (($ ARG_1 + $ ARG_2))" exit else echo "Prompt --sum or --molt as option, then two numbers as an argument for the sum. " exit 1 fi

In this script I assign the value of $ 1, $ 2, $ 3 respectively to $ ARG_, $ ARG_1, $ ARG_2 for convenience,

  • In the 1 parameter: the execution mode is required, ie if the program will have to add or multiply the two numbers of the parameters $ 2 and $ 3, if $ 1 does not correspond to either –sum or –molt the program will exit with return 1 ( not successfully completed)
  • In the other 2: without verification - 2 numbers are required, in the event that $ 2 and $ 3 were not equal to two numbers, the result is 0 but the two parameters will always be identified regardless of the value

So I could easily do this:

./script.sh --sum 3 4

performs the sum between 3 and 4

./script.sh --molt 3 4 

multiply between 3 and 4.
We see that in every if-elif-else block there is a for-in block with variable $ @: that block takes the values ​​of $ @: in the variable $ @ are stored all the values ​​of $ 1, $ 2, $ 3, $ 4 ... can be infinite ... its content changes according to the values ​​passed on the command line, so that block assigns $ the values ​​of $ @ which is nothing more than an array, then prints for each single value a string in which it is possible to see the values ​​contained in $ @ (in our case $ 1, $ 2, $ 3). Obviously as regards the functions: these do not take the same value as $ 1, $ 2 and so on if you do not assign it to them in the parameters, to overcome this, just use any other value.
If I want to use the same parameters of the command line I use this "style":

#! / bin / sh ARG = $ 1 funct () {echo $ 1} funct $ ARG

So if I run: ./script.sh hello will be printed on the screen Hello
Otherwise:

#! / bin / sh ARG = $ 1 echo $ ARG funct () {echo $ 1} funct hello


Create libraries
Libraries are nothing but programs that allow other programs to perform certain operations, for example, libncurses, which allows us to create (if we are developers) semi-graphical interfaces thanks to its functions that we will refer to in our source (C / C ++), or even the standard GNU / C ++ libraries that allow us to use streams for input and output, gtk for graphical interfaces, mechanize (python) ...
Without these libraries we would not be able to create certain programs, or rather we could ... but we should create them! We can create a "library" for shellscripts and then reuse it in a very simple way, usually a programmer creates his own library, for a big program, so he wants to reuse the code, and / or he wants to divide the program into modules.

Closing this parenthesis ...
a library is a set of functions, so this will be the content of the file we will call "lib.sh"

#! / bin / sh doSomething () {echo "Hello"} doSomma () {SOM = $ (($ 1 + $ 2)) echo $ SOM return $ SOM} doMolt () {MOLT = $ (($ 1 * $ 2) ) echo $ MOLT return $ MOLT}

obviously if we execute it nothing happens, the file contains the functions that have only been defined, but does not recall them in any way, and must NOT recall them, they will be recalled later by the actual program. Each library must have a well-defined name ... I would call this libcalculator.sh to define what the purpose of this library is.

#! / bin / sh source "./lib.sh" doSomething doSomma 1 2 doMolt 2 3 exit 0 

This is our usual script.sh instead
the ./lib.sh file is included from the current directory (if this was not the case we should have written the path) with the source statement. It is the same as including a C / C ++ header file in this way

#include #include "lib.h"

or a Java module with the import statement

import java.lang. *; import my.lib.hlib;

or even a Python module

import os import myomodule

Once the parenthesis is closed, we can see how script.sh is cleaner and more understandable, the functions will be called directly in script.sh with the relative parameters. We could have done the same thing by including the functions in the same file and calling them directly. But it would have been less understandable. This instead guarantees a cleanliness of the code 😉

All scripts have been tested and are functional, unless there is a copy / paste error by the author or reader.

I hope you understand how a shell and shell scripts work. Let me know in the comments 😉
Obviously this is not intended as an introduction and not a reference of study. 😉 On Amazon there are many free books on shell scripting. Help, take it like this 🙂
However if you already have programming experiences you are already able to write small scripts, if you have no experience I suggest you read the article first ... then study on the books 😛 even if you read well and understand what I explained briefly you would be able to write some scripts.
See you soon!

Receive the latest posts by email

Enter the email and choose the inscriptions on the new page

InTheBit.it
Added devices
  • Compare Smartphone (0)
  • Compare Notebook (0)
Compare