Linux bash scripts. Writing scripts in Bash. Conditions. Multiple choice

Today we'll talk about bash scripts. These are command line scripts written for the bash shell. There are other shells like zsh, tcsh, ksh, but we will focus on bash. This material is intended for everyone, the only condition is the ability to work in the Linux command line.



Command line scripts are sets of the same commands that can be entered from the keyboard, assembled into files and united by some common purpose. In this case, the results of the work of teams can be either of independent value, or serve as input data for other teams. Scripting is a powerful way to automate frequently performed actions.

So, if we talk about the command line, it allows you to execute several commands at one time, entering them separated by semicolons:

Pwd; whoami
In fact, if you've tried it in your terminal, your first bash script that involves two commands has already been written. It works like this. First, the pwd command displays information about the current working directory, then the whoami command displays information about the user under which you are logged in.

Using this approach, you can combine as many commands as you like on one line, the limitation is only in the maximum number of arguments that can be passed to the program. You can determine this limitation using the following command:

Getconf ARG_MAX
The command line is a great tool, but you have to enter commands every time you need them. What if you write a bunch of commands to a file and just call that file to execute them? In fact, the file we are talking about is called a command line script.

How bash scripts work

Create an empty file using the touch command. In its first line, we need to indicate which shell we are going to use. We are interested in bash, so the first line of the file will be like this:

#! / bin / bash
In other lines of this file, the hash character is used to denote comments that the shell does not process. However, the first line is a special case, here a hash followed by an exclamation point (this sequence is called shebang) and the path to bash indicate to the system that the script was written for bash.

Shell commands are delimited with line feeds, comments are delimited with hash marks. This is how it looks:

#! / bin / bash # This is a comment pwd whoami
Here, as well as on the command line, you can write commands on one line, separated by semicolons. However, writing the commands on separate lines makes the file easier to read. In any case, the shell will process them.

Setting script file permissions

Save the file with the name myscript and the bash script is almost done. Now all that remains is to make this file executable, otherwise, trying to run it, you will encounter the Permission denied error.


Attempting to run a script file with incorrectly configured permissions

Let's make the file executable:

Chmod + x ./myscript
Now let's try to execute it:

./myscript
After setting the permissions, everything works as it should.


Successfully running bash script

Displaying messages

The echo command is used to output text to the Linux console. Let's take advantage of the knowledge of this fact and edit our script, adding explanations to the data that are displayed by the commands already in it:

#! / bin / bash # our comment is here echo "The current directory is:" pwd echo "The user logged in is:" whoami
This is what happens after running the updated script.


Displaying messages from a script

Now we can print explanatory notes using the echo command. If you don't know how to edit a file using Linux tools, or haven’t seen the echo command before, take a look at this resource.

Using Variables

Variables allow you to store information in a script file, for example, the results of commands to be used by other commands.

There is nothing wrong with executing individual commands without storing the results of their work, but the possibilities of this approach are very limited.

There are two types of variables that can be used in bash scripts:

  • Environment Variables
  • User variables

Environment Variables

Sometimes shell commands need to work with some system data. For example, here's how to display the home directory of the current user:

#! / bin / bash # display user home echo "Home for the current user is: $ HOME"
Please note that we can use the system variable $ HOME in double quotes, this will not prevent the system from recognizing it. This is what happens if you run the above script.


Using an environment variable in a script

What if you want to display the dollar sign on the screen? Let's try this:

Echo "I have $ 1 in my pocket"
The system detects the dollar sign in the quoted string and thinks we referenced a variable. The script will try to display the value of the undefined variable $ 1. This is not what we want. What to do?

A backslash escape character before the dollar sign can help in this situation:

Echo "I have \ $ 1 in my pocket"
The script will now output exactly what is expected.


Using an Escape Sequence to Output a Dollar Sign

User variables

In addition to environment variables, bash scripts allow you to set and use your own variables in the script. These variables hold their value until the script finishes executing.

As with system variables, user variables can be accessed using the dollar sign:
TNW-CUS-FMP - promo code for 10% discount on our services, available for activation within 7 days
#! / bin / bash # testing variables grade = 5 person = "Adam" echo "$ person is a good boy, he is in grade $ grade"
This is what happens after running such a script.


Custom variables in a script

Command substitution

One of the most useful features of bash scripts is the ability to extract information from the output of commands and assign it to variables, which allows this information to be used anywhere in the script file.

This can be done in two ways.

  • With the backtick ""
  • Using the $ ()
Using the first approach, be sure not to use a single quote instead of the backtick. The command must be enclosed in two such icons:

Mydir = `pwd`
In the second approach, the same thing is written like this:

Mydir = $ (pwd)
And the script, in the end, may look like this:

#! / bin / bash mydir = $ (pwd) echo $ mydir
During its operation, the output of the pwd command will be saved in the mydir variable, the contents of which, using the echo command, will go to the console.


A script that stores the results of a command in a variable

Mathematical operations

To perform mathematical operations in a script file, you can use a construction like $ ((a + b)):

#! / bin / bash var1 = $ ((5 + 5)) echo $ var1 var2 = $ (($ var1 * 2)) echo $ var2


Math operations in a script

If-then control construct

Some scenarios require control of the command execution flow. For example, if some value is greater than five, you need to perform one action, otherwise - another. This is applicable in a great many situations, and the if-then control construct will help us here. In its simplest form, it looks like this:

If command then command fi
And here's a working example:

#! / bin / bash if pwd then echo "It works" fi
In this case, if the pwd command completes successfully, the text "it works" will be displayed in the console.

Let's use our knowledge and write a more complex script. Let's say you need to find a certain user in / etc / passwd, and if you can find it, report that it exists.

#! / bin / bash user = likegeeks if grep $ user / etc / passwd then echo "The user $ user Exists" fi
This is what happens after running this script.


Search for a user

Here we have used the grep command to find the user in the / etc / passwd file. If you are unfamiliar with the grep command, its description can be found.

In this example, if a user is found, the script will display an appropriate message. What if the user cannot be found? In this case, the script will simply end its execution without telling us anything. I would like him to tell us about this too, so we will improve the code.

If-then-else control construct

In order for the program to be able to report both the results of a successful search and a failure, we will use the if-then-else construction. Here's how it works:

If command then commands else commands fi commands
If the first command returns zero, which means its successful execution, the condition will be true and execution will not follow the else branch. Otherwise, if something other than zero is returned, which means failure, or a false result, the commands after the else will be executed.

Let's write a script like this:

#! / bin / bash user = anotherUser if grep $ user / etc / passwd then echo "The user $ user Exists" else echo "The user $ user doesn’t exist" fi
Its execution went along the else branch.


Running a script with an if-then-else construction

Well, let's continue to move on and ask ourselves about more difficult conditions. What if you need to check more than one condition, but several? For example, if the desired user is found, you need to display one message, if some other condition is met - another message, and so on. In such a situation, nested conditions will help us. It looks like this:

If command1 then commands elif command2 then fi commands
If the first command returns zero, which indicates its successful execution, the commands in the first then block will be executed, otherwise, if the first condition turns out to be false, and if the second command returns zero, the second block of code will be executed.

#! / bin / bash user = anotherUser if grep $ user / etc / passwd then echo "The user $ user Exists" elif ls / home then echo "The user doesn’t exist but anyway there is a directory under / home" fi
In such a script, you can, for example, create a new user using the useradd command if the search did not return any results, or do something else useful.

Comparing numbers

Numeric values ​​can be compared in scripts. Below is a list of the relevant commands.
n1 -eq n2 Returns true if n1 is equal to n2.
n1 -ge n2 Returns true if n1 is greater than or equal to n2.
n1 -gt n2 Returns true if n1 is greater than n2.
n1 -le n2 Returns true if n1 is less than or equal to n2.
n1 -lt n2 Returns true if n1 is less than n2.
n1 -ne n2 Returns true if n1 is not equal to n2.

Let's try one of the comparison operators as an example. Note that the expression is enclosed in square brackets.

#! / bin / bash val1 = 6 if [$ val1 -gt 5] then echo "The test value $ val1 is greater than 5" else echo "The test value $ val1 is not greater than 5" fi
This is what this command will output.


Comparing numbers in scripts

The value of the variable val1 is greater than 5, as a result, the then branch of the comparison operator is executed and a corresponding message is displayed on the console.

String comparison

You can also compare string values ​​in scripts. Comparison operators look pretty simple, but string comparison operations have certain peculiarities, which we will touch on below. Here is a list of operators.
str1 = str2 Tests strings for equality, returns true if strings are identical.
s tr1! = str2 Returns true if the strings are not identical.
str1< str2 Возвращает истину, если str1 меньше, чем str2 .
str1> str2 Returns true if str1 is greater than str2.
-n str1 Returns true if str1 is greater than zero.
-z str1 Returns true if the length of str1 is zero.

Here's an example of comparing strings in a script:

#! / bin / bash user = "likegeeks" if [$ user = $ USER] then echo "The user $ user is the current logged in user" fi
As a result of the script execution, we get the following.


Comparing strings in scripts

Here is one feature of string comparison worth mentioning. Namely, the operators ">" and "<» необходимо экранировать с помощью обратной косой черты, иначе скрипт будет работать неправильно, хотя сообщений об ошибках и не появится. Скрипт интерпретирует знак «>"As an output redirection command.

This is how working with these operators looks like in code:

#! / bin / bash val1 = text val2 = "another text" if [$ val1 \>
Here are the results of the script.


Comparison of strings, issued warning

Note that the script, although executed, generates a warning:

./myscript: line 5: [: too many arguments
To get rid of this warning, enclose $ val2 in double quotes:

#! / bin / bash val1 = text val2 = "another text" if [$ val1 \> "$ val2"] then echo "$ val1 is greater than $ val2" else echo "$ val1 is less than $ val2" fi
Now everything works as it should.


String comparison

Another feature of the operators ">" and "<» заключается в том, как они работают с символами в верхнем и нижнем регистрах. Для того, чтобы понять эту особенность, подготовим текстовый файл с таким содержимым:

Likegeeks likegeeks
Let's save it, giving the name myfile, and then execute the following command in the terminal:

Sort myfile
It will sort the lines from the file like this:

Likegeeks Likegeeks
The sort command, by default, sorts lines in ascending order, that is, the lowercase letter in our example is smaller than the uppercase one. Now let's prepare a script that will compare the same strings:

#! / bin / bash val1 = Likegeeks val2 = likegeeks if [$ val1 \> $ val2] then echo "$ val1 is greater than $ val2" else echo "$ val1 is less than $ val2" fi
If you run it, it turns out that the opposite is true - the lowercase letter is now larger than the uppercase one.


Sort command and line comparison in a script file

Comparison commands have fewer uppercase letters. The string comparison here is done by comparing the ASCII character codes, the sort order thus depends on the character codes.

The sort command, in turn, uses the sort order specified in the system language settings.

File checks

The commands below are probably the most commonly used in bash scripts. They allow you to check various conditions regarding files. Here is a list of these commands.
-d file Checks if a file exists and is a directory.
-e file Checks if the file exists.
-f file Checks if the file exists and is a file.
-r file Checks if the file exists and is readable.
-s file Check if the file exists and is not empty.
-w file Checks if the file exists and is writable.
-x file Checks if the file exists and is executable.
file1 -nt file2 Checks if file1 is newer than file2.
file1 -ot file2 Checks if file1 is older than file2.
-O file Checks if the file exists and is owned by the current user.
-G file Checks if the file exists and if its group ID matches the group ID of the current user.

These commands, as well as many others discussed today, are easy to remember. Their names, being abbreviations from various words, directly indicate the checks they perform.

Let's try one of the commands in practice:

#! / bin / bash mydir = / home / likegeeks if [-d $ mydir] then echo "The $ mydir directory exists" cd $ mydir ls else echo "The $ mydir directory does not exist" fi
This script, for an existing directory, will display its contents.


Displaying the contents of a directory

We believe that you can experiment with the rest of the commands on your own, they all apply in the same way.

Outcomes

Today we covered how to get started writing bash scripts and covered some basic things. In fact, the topic of bash programming is huge. This article is a translation of the first part of a large series of 11 articles. If you want to continue right now - here is a list of the originals of these materials. For convenience, this includes the translation you just read.

No matter how simple the graphical interface in Linux is and no matter how many functions there are, there are still tasks that are more convenient to solve through the terminal. Firstly, because it is faster, and secondly, not all machines have a graphical interface, for example, on servers, all actions are performed through the terminal, in order to save computing resources.

If you are already a more experienced user, you probably often perform various tasks through the terminal. Often there are tasks for which you need to execute several commands in turn, for example, to update the system, you must first update the repositories, and only then download the new versions of the packages. This is just an example and there are a lot of such actions, even taking a backup and uploading the copied files to a remote server. Therefore, in order not to type the same commands several times, you can use scripts. In this article we will look at writing scripts in Bash, look at the basic operators, and how they work, so to speak, bash scripts from scratch.

A script, or as it is also called, a script, is a sequence of commands that are read and executed in turn by an interpreter program, in our case it is a command line program - bash.

A script is a plain text file that lists the usual commands that we are used to entering manually, as well as the specified program that will execute them. The loader that will execute the script does not know how to work with environment variables, so it needs to be passed the exact path to the program to run. And then he will already transfer your script to this program and execution will begin.

The simplest example of a Bash shell script:

! / bin / bash
echo "Hello world"

The echo utility prints the string passed to it as a parameter to the screen. The first line is special, it specifies the program that will execute the commands. Generally speaking, we can create a script in any other programming language and specify the desired interpreter, for example, in python:

! / usr / bin / env python
print ("Hello world")

Or in PHP:

! / usr / bin / env php
echo "Hello world";

In the first case, we directly pointed to the program that will execute the commands, in the next two we do not know the exact address of the program, so we ask the env utility to find it by name and run it. This approach is used in many scripts. But that is not all. On a Linux system, in order for the system to execute a script, you need to set the executable flag on the file with it.

This flag does not change anything in the file itself, it only tells the system that this is not just a text file, but a program and it needs to be executed, open the file, find out the interpreter and execute it. If no interpreter is specified, the user's interpreter will be used by default. But since not everyone uses bash, you need to specify this explicitly.

To run:

chmod ugo + x script_file

Now we run our small first program:

./script_file

Everything works. You already know how to write a small script for, say, an update. As you can see, the scripts contain the same commands that are executed in the terminal, they are very easy to write. But now we will complicate the task a little. Since a script is a program, it needs to make some decisions by itself, store the results of command execution and execute loops. All this is done by the Bash shell. True, everything is much more complicated here. Let's start simple.

Variables in scripts

Writing scripts in Bash rarely goes without storing temporary data, which means creating variables. No programming language is complete without variables, and neither is our primitive shell language.

You may have met with environment variables before. So, these are the same variables and they work in the same way.

For example, let's declare a variable string:

string = "Hello world"

The value of our string is quoted. But in reality, quotes are not always needed. Here the main bash principle is preserved - a space is a special character, a separator, so if you do not use quotes, world will already be considered a separate command, for the same reason we do not put spaces before and after the equal sign.

The $ symbol is used to display the value of a variable. For example:

Let's modify our script:

! / bin / bash
string1 = "hello"
string2 = world
string = $ string1 $ string2
echo $ string

And check:

Bash does not distinguish between variable types in the same way that high-level languages ​​like C ++, you can assign either a number or a string to a variable. Equally all of this will be considered a string. The shell only supports string concatenation, just write down the variable names in a row:

! / bin / bash
string1 = "hello"
string2 = world
string = $ string1 $ string2 \ and \ me
string3 = $ string1 $ string2 "and me"
echo $ string3

We check:

Please note that as I said, quotes are optional if there are no special characters in the string. Take a closer look at both ways of string concatenation, here is also a demonstration of the role of quotes. If you need more complex ways of processing strings or arithmetic operations, this is not included in the capabilities of the shell, for this you use the usual utilities.

Variables and command output

Variables would not be so useful if it was impossible to write the result of executing the utilities in them. For this, the following syntax is used:

$(command )

With this construction, the output of the command will be redirected directly to where it was called from, and not to the screen. For example, the date utility returns the current date. These commands are equivalent:

Do you understand? Let's write a script where hello world and date will be displayed:

string1 = "hello world"
string2 = $ (date)

string = $ string1 $ string2

Now that you know enough about variables, you're ready to create a bash script, but that's not all. Next, we'll look at parameters and control constructs. Let me remind you that these are all ordinary bash commands, and you do not need to save them in a file, you can execute them immediately on the go.

Script parameters

It is not always possible to create a bash script that does not depend on user input. In most cases, you need to ask the user what action to take or which file to use. When calling the script, we can pass parameters to it. All of these parameters are available as variables with names as numbers.

A variable named 1 contains the value of the first parameter, variable 2, the second, and so on. This bash script will print the value of the first parameter:

! / bin / bash
echo $ 1

Control constructs in scripts

Creating a bash script would not be so useful without the ability to analyze certain factors, and perform the necessary actions in response to them. This is quite a complex topic, but it is very important in order to create a bash script.

Bash has a command for checking conditions.The syntax is as follows:

if command_condition
then
command
else
command
fi

This command checks the completion code of the condition command, and if 0 (success) then executes the command or several commands after the then word, if the completion code 1 executes the else block, fi means the end of the command block.

But since we are most often interested not in the return code of the command, but in the comparison of strings and numbers, the [[command was introduced, which allows us to perform various comparisons and issue a return code depending on the result of the comparison. Its syntax is:

[[parameter1 operator parameter2]]

For comparison, we use the operators already familiar to us<,>, =,! = and so on. If the expression is true, the command will return 0, if not - 1. You can test its behavior a little in the terminal. The return code of the last command is stored in the $? Variable:

Now, combine all this and get a script with a conditional expression:

! / bin / bash
if [[$ 1> 2]]
then
echo $ 1 "more than 2"
else
echo $ 1 "less than 2 or 2"
fi

Of course, this design has more powerful capabilities, but it is too difficult to cover them in this article. Perhaps I will write about this later. For now, let's move on to loops.

Loops in scripts

The advantage of programs is that we can specify in several lines what actions need to be performed several times. For example, it is possible to write scripts in bash, which consist of only a few lines, and are executed for hours, analyzing the parameters and performing the necessary actions.

Let's look at the for loop first. Here is its syntax:

for variable in list
do
command
done

Loops through the entire list, and assigns the value from the list to the variable in turn, after each assignment, it executes the commands located between do and done.

For example, let's iterate over five digits:

for index in 1 2 3 4 5
do
echo $ index
done

Or you can list all files in the current directory:

for file in $ (ls -l); do echo "$ file"; done

As you understand, you can not only display names, but also perform the necessary actions, this is very useful when creating a bash script.

The second loop we'll look at is a while loop, it runs as long as the condition command returns 0, success. Consider the syntax:

while command condition
do
command
done

Let's consider an example:

! / bin / bash
index = 1
while [[$ index< 5 ]]
do
echo $ index
let "index = index + 1"
done

As you can see, everything is executed, the let command simply performs the specified mathematical operation, in our case it increases the value of the variable by one.

I would like to note one more thing. Constructs such as while, for, if are designed to be written in several lines, and if you try to write them in one line, you will get an error. But nevertheless it is possible, for this, where there should be a line feed, put a semicolon ";". For example, the previous loop could have been executed as a single line:

index = 1; while [[$ index< 5 ]]; do echo $index; let "index=index+1"; done;

Everything is very simple, I tried not to complicate the article with additional terms and capabilities of bash, only the most basic. In some cases, you may need to make a gui for a bash script, then you can use programs such as zenity or kdialog, with the help of them it is very convenient to display messages to the user and even request information from him.

conclusions

Now you understand the basics of scripting in linux and can write the script you need, for example, for backups. I tried to look at bash scripts from scratch. Therefore, not all aspects were considered. Perhaps we will return to this topic in one of the next articles.

For writing a simple bash script, we need to follow these simple steps:

How it all works:

the first line of our script #! / bin / bash is essential for our script to execute successfully.

second line mkdir testdir creates testdir directory

the third line cd testdir allows you to go to the created testdir directory

command touch on next line touch file1 file2 file3 creates three files

and the last command on the ls -al line of our script displays the contents of the current directory, in which, thanks to the previous line, three empty files appeared.

As we can see, in our simple script all commands start on a new line. Each line, when starting the script, sequentially performs its work, performing certain actions.

If you daily run a chain of any identical commands (with constant parameters) in Linux, then it may make sense for you to write the same simple bash script which will save you time and automate your work.

Of course, all those who communicate with Linux at least once have dealt (at least they have heard for sure) with the BASH command shell. But BASH is not only a command shell, it is also an excellent scripting programming language.
The purpose of this article is to acquaint users with bash more closely, to tell about the syntax, basic techniques and tricks of the language, so that even an ordinary user can quickly write a simple script to perform daily (-weekly, -monthly) routine work or, say, “on the knee »Create a script for a directory backup.

Introduction

BASH - Bourne-Again SHell (which can be translated as "reborn walk", or "Bourne walked again (creator of sh)"), the most popular shell in Unix-like systems, especially GNU / Linux. Below are a number of built-in commands that we will use to create our scripts.

Break exit from a for, while, or until loop
continue executing the next iteration of a for, while, or until loop
echo print arguments, separated by spaces, to standard output
exit exit shell
export marks arguments as variables for passing to child processes in the environment
hash remembers the fully qualified pathnames of the commands specified as arguments, so as not to look for them on the next call
kill sends a kill signal to the process
pwd displays the current working directory
read reads a string from shell input and uses it to assign values ​​to the specified variables. \
return causes the shell function to exit with the specified value
shift moves positional parameters to the left
test evaluates a conditional expression
times displays the username and system time used by the shell and its descendants
trap specifies the commands to run when the shell receives a signal
unset causes destruction of shell variables
wait waits for the child to exit and reports the exit state.

And of course, in addition to built-in commands, we will use a whole bunch of external, separate command-programs, which we will get acquainted with already in the process.

What you need to know from the start

1. Any bash script must start with the line:

#! / bin / bash
on this line after #! the path to the bash interpreter is indicated, so if you have it installed in a different place (where, you can find out by typing whereis bash), change it to your path.
2. Comments begin with a # character (except for the first line).
3. In bash, variables have no type (they will be discussed below)

Variables and script parameters

I will give as an example a small example that we will analyze:

#! / bin / bash
# specify where we store the bash interpreter
parametr1 = $ 1 # assign the variable parametr1 the value of the first parameter of the script
script_name = $ 0 # assign the script_name variable the value of the script name
echo "You ran a script with the name $ script_name and the parameter $ parametr1" # echo command outputs a specific line, variables are accessed via $ variable_name.
echo "You ran a script with the name $ script_name and the parameter $ parametr1" # we see other quotes here, the difference is that there is no variable substitution in single quotes.
exit 0 # Exit with code 0 (successful completion of the script)

[email protected]: ~ $ ./test.sh qwerty
You have run a script named. / Test.sh with qwerty parameter
You have run a script named $ script_name and parameter $ parametr1

After we have seen how to use variables and pass parameters to the script, it's time to get acquainted with reserved variables:

$ DIRSTACK - the contents of the top of the directory stack
$ EDITOR - default text editor
$ EUID - Effective UID. If you used su to execute commands from another user, then this variable contains the UID of that user, while ...
$ UID - ... contains the real identifier, which is set only at login.
$ FUNCNAME is the name of the current function in the script.
$ GROUPS - array of groups the current user belongs to
$ HOME - user's home directory
$ HOSTNAME is your hostname
$ HOSTTYPE - machine architecture.
$ LC_CTYPE - internal variable that defines the character encoding
$ OLDPWD - old working directory
$ OSTYPE - OS type
$ PATH - program search path
$ PPID - parent process identifier
$ SECONDS - script running time (in seconds)
$ # - the total number of parameters passed to the script
$ * - all arguments are not passed to the script (output to string)
[email protected]- the same as the previous one, but the parameters are displayed in a column
$! - PID of the last process running in the background
$$ - PID of the script itself

Conditions

Conditional operators, I think, are familiar to almost everyone who has ever tried to write programs on something. In bash, conditions are traced. way (as usual with an example):
#! / bin / bash
source = $ 1 # put the first script parameter into the source variable
dest = $ 2 # add the second script parameter to the dest variable

If [["$ source" -eq "$ dest"]] # in quotation marks indicate the names of the variables to be compared. -eq - boolean comparison denoting "equal"
then # if they are indeed equal, then
echo "Application $ dest and source $ source are the same file!" # display an error message, because $ source and $ dest are equal
exit 1 # exit with an error (1 - error code)
else # if they are not equal
cp $ source $ dest # then execute the cp command: copy the source to the destination
echo "Successful copying!"
fi # denote the end of the condition.

The result of the script execution:
[email protected]: ~ $ ./primer2.sh 1 1
App 1 and source 1 are the same file!
[email protected]: ~ $ ./primer2.sh 1 2
Successful copying!

The if-then-else structure is used as follows:
if<команда или набор команд возвращающих код возврата(0 или 1)>
then
<если выражение после if истино, то выполняется этот блок>
else
<если выражение после if ложно, тот этот>
The structures [[, [, test, (()) or any other (or several) linux-command can act as commands returning the return code.
test - used for logical comparison. after the expression, a closing parenthesis "]" is required
[- a synonym for the test command
[[- extended version "[" (since version 2.02) (as in the example), inside which || (or), & (and). Must have a closing parenthesis "]]"
(()) - mathematical comparison.
to build multi-tiered conditions of the form:
if ...
then ....
else
if ....
then ....
else ....

For brevity and readability of the code, you can use the structure:
if ..
then ...
elif ...
then ...
elif ...

Conditions. Multiple choice

If it is necessary to compare a single variable with a large number of parameters, then it is more expedient to use the case statement.
#! / bin / bash
echo "Select an editor to run:"
echo "1 Run nano program"
echo "2 Run vi program"
echo "3 Start the emacs program"
echo "4 Exit"
read doing # here we read into the variable $ doing from standard input

Case $ doing in
1)
/ usr / bin / nano # if $ doing contains 1, then run nano
;;
2)
/ usr / bin / vi # if $ doing contains 2, then run vi
;;
3)
/ usr / bin / emacs # if $ doing contains 3 then run emacs
;;
4)
exit 0
;;
*) # if something is entered from the keyboard that is not described in the case, do the following:
echo "Invalid action entered"

Esac # end of a case statement.

Result of work:
[email protected]: ~ $ ./menu2.sh
Select an editor to run:
1 Starting the nano program
2 Starting the vi program
3 Starting the emacs program
4 Exit

After selecting a number and pressing Enter, the editor you have chosen will start (unless, of course, all the paths are specified correctly, and you have these editors installed :))
Here is a list of logical operators that are used for the if-then-else-fi construction:
-z # line is empty
-n # line is not empty
=, (==) # strings are equal
! = # strings are unequal
-eq # equal
-ne # unequal
-lt, (<) # меньше
-le, (<=) # меньше или равно
-gt, (>) # more
-ge, (> =) # greater than or equal
! # negation of boolean expression
-a, (&&) # logical AND
-o, (||) # logical "OR"

We figured out the basics of the language and conditions so as not to overload the article, I will split it into several parts (for example, into 3). In the second part, we will analyze the loop operators and the execution of mathematical operations.

UPD: Fixed some bugs
UPD: Updated the part about if-then-else conditions

Writing scripts in Linux (learning by example)

———————————————————————————-

1. Introduction

What you need to write scripts
Proficiency in command line tools and their required options.
Basic knowledge of English at the elementary school level will not hurt.

Why scripts are needed
First, the administration of a linux server, to one degree or another, is reduced to the systematic execution of the same commands. Moreover, it is not necessary that these commands are performed by a person. They can be programmed to be executed by the machine.
Secondly, even just performing a common task, which (suddenly) amounts to 20-1000 ... repetitive operations are MUCH easier to implement in a script.

What is a script
A script is a set of instructions that a computer must execute in a specific order and at a specific time. Instructions can be either internal shell commands (loops, conditions, processing text information, working with environment variables, etc.), or any program that we execute in the console with the necessary parameters.

How to write a script
In our case, the script will be a text file with execution attributes. If a script file begins with the # !, which is called sha-bang in the UNIX world, this tells the system which interpreter to use to execute the script. If it is difficult to understand, then just remember that we will start writing all scripts exactly from the line #! / Bin / bash or #! / Bin / sh, and then commands and comments to them will follow.

Parting words
I sincerely advise you to write as many comments as possible to almost every line in the script. Time will pass and you will need to change or modernize the script written once. If you don’t remember or understand what is written in the script, then it becomes difficult to change it, it’s easier to write from scratch.

What scripts we might need:

    setting firewall rules when the system boots.
    performing backup of settings and data.
    adding mailboxes to the mail server (more precisely to the mysql database)
    which launches at a certain time (preferably every night) a program that scans the proxy server logs and issues a convenient web report on the amount of downloaded traffic.
    sending us by mail information that someone has gained access to our server via ssh, the connection time and the client's address.

About scripting techniques
We create a text file, edit it, set execution permissions, launch, check errors, fix, launch, check errors ...
When everything is licked and working correctly, we put it in autoload or in the scheduler for a certain time.

———————————————————————————-

2. Learning to write scripts in the internal BASH language
original: https://www.linuxconfig.org/Bash_scripting_Tutorial

This tutorial assumes no prior knowledge of scripting (scripting) techniques using the internal Bash language. With this tutorial, you will soon find that scripting is a very easy task. Let's start our tutorial with a simple script that outputs the string "Hello World!" (translated from English - Hello everyone!)

1. Scenario "Hello everyone"
Here's your first bash script example:

#! / bin / bash
echo "Hello World"

Go to the directory containing our hello_world.sh file and make it executable:

Code: Select everything $ chmod + x hello_world.sh

Run the script for execution

Code: Select All $ ./hello_world.sh

2. A simple archiving bash script

#! / bin / bash
tar -czf myhome_directory.tar.gz / home / user

Code: Select All $ ./backup.sh

$ du -sh myhome_directory.tar.gz
41M myhome_directory.tar.gz

3. Working with variables
In this example, we declare a simple variable and print it to the screen using the echo command

#! / bin / bash
STRING = "HELLO WORLD !!!"
echo $ STRING

Code: Select All $ ./hello_world.sh
HELLO WORLD !!!

Our archiving script with variables:

#! / bin / bash
OF = myhome_directory _ $ (date +% Y% m% d) .tar.gz
IF = / home / user
tar -czf $ OF $ IF

Code: Select All $ ./backup.sh
tar: Removing leading "\" from member names
$ du -sh * tar.gz
41M myhome_directory_20100123.tar.gz

3.1 Global and local variables

#! / bin / bash
# Declare a global variable
# Such a variable can be used anywhere in this script
VAR = "global variable"
function bash (
# Declare a local variable
# Such a variable is valid only for the function in which it was declared
local VAR = "local variable"
echo $ VAR
}
echo $ VAR
bash
# Note that the global variable hasn't changed
echo $ VAR

Code: Select all $ ./variables.sh
global variable
local variable
global variable

4. Passing arguments to the script

#! / bin / bash
# Use predefined variables to access arguments
# Display arguments to the screen
echo $ 1 $ 2 $ 3 '-> echo $ 1 $ 2 $ 3'

# We can also access the arguments through the special array args = (“ [email protected]»)
# Display arguments to the screen
echo $ (args) $ (args) $ (args) ‘-> args = (“ [email protected]"); echo $ (args) $ (args) $ (args) '

# Use a variable [email protected] to output all arguments at once
echo [email protected]‘-> echo [email protected]

Use the $ # variable to display the number of arguments passed to the script
echo Number of arguments passed: $ # ‘-> echo Number of arguments passed: $ #’

Code: Select All $ ./arguments.sh Bash Scripting Tutorial
Bash Scripting Tutorial -> echo $ 1 $ 2 $ 3
Bash Scripting Tutorial -> args = (" [email protected]"); echo $ (args) $ (args) $ (args)
Bash Scripting Tutorial -> echo [email protected]
Number of arguments passed: 3 -> echo Number of arguments passed: $ #

5. Executing shell commands in a script

#! / bin / bash
# use backticks "" "" to execute shell command
echo `uname -o`
# now let's try without quotes
echo uname -o

Code: Select all $ uname -o
GNU / Linux
$ ./bash_backtricks.sh
GNU / Linux
uname -o

As you can see, in the second case, the command itself was displayed, and not the result of its execution.

6. Reading user input (interactivity)

#! / bin / bash
echo -e "Hi, please type the word: \ c"
read word
echo "The word you entered is: $ word"
echo -e “Can you please enter two words? "
read word1 word2
echo "Here is your input: \" $ word1 \ "\" $ word2 \ ""
echo -e “How do you feel about bash scripting? "
# read command now stores a reply into the default build-in variable $ REPLY
read
echo “You said $ REPLY, I'm glad to hear that! "
echo -e “What are your favorite colors? "
# -a makes read command to read into an array
read -a colors
echo "My favorite colors are also $ (colors), $ (colors) and $ (colors) :-)"

Code: Select all $ ./read.sh
Hi, please type the word: something
The word you entered is: something
Can you please enter two words?
Debian Linux
Here is your input: "Debian" "Linux"
How do you feel about bash scripting?
good
You said good, I "m glad to hear that!
What are your favorite colors?
blue green black
My favorite colors are also blue, green and black :-)

7. Using a trap

#! / bin / bash
# declare a trap
trap bashtrap INT
# clear the screen
clear;
# the hook function is executed when the user presses CTRL-C:
# The screen will display => Executing bash trap subrutine!
# but the script will continue to execute
bashtrap ()
{
echo "CTRL + C Detected! ... executing bash trap!"
}
# script will count to 10
for a in `seq 1 10`; do
echo "$ a / 10 to Exit."
sleep 1;
done
echo "Exit Bash Trap Example !!!"

Code: Select All $ ./trap.sh
1/10
2/10
3/10
4/10
5/10
6/10

7/10
8/10
9/10
CTRL + C Detected! ... executing bash trap!
10/10
Exit Bash Trap Example !!!

As you can see, the key combination Ctrl-C did not stop the script execution.

8. Arrays
8.1 Declaring a simple array

#! / bin / bash
# Declare a simple array with 4 elements
ARRAY = (‘Debian Linux’ ’‘ Redhat Linux ’Ubuntu Linux)
# Get the number of elements in the array
ELEMENTS = $ (# ARRAY [@])

# output in a loop each element of the array
for ((i = 0; i<$ELEMENTS;i++)); do
echo $ (ARRAY [$ (i)])
done

Code: Select all $. / Arrays.sh
Debian Linux
Redhat Linux
Ubuntu
Linux

8.2 Fill the array with values ​​from the file

#! / bin / bash
# Declare an array
declare -a ARRAY
# Exec command # stdin (usually the keyboard) will be produced from this file. This makes it possible to read
# the contents of the file, line by line, and parse each line entered with sed and / or awk.
exec 10 let count = 0

while read LINE<&10; do

ARRAY [$ count] = $ LINE
((count ++))
done

echo Number of elements: $ (# ARRAY [@])
# Outputting array values
echo $ (ARRAY [@])
# close the file
exec 10> & -

Code: Select all $ cat bash.txt
Debian Linux
Redhat Linux
Ubuntu
Linux
$ ./arrays.sh
Number of elements: 4
Debian Linux Redhat Linux Ubuntu Linux

9. If-then-otherwise conditions
9.1. Simple use of "if-otherwise" conditions
Pay attention to the spaces in square brackets, without which the condition will not work.

#! / bin / bash
directory = "./ BashScripting"

# check if the directory exists
if [-d $ directory]; then
echo "Directory exists"
else
echo "Directory does not exists"
fi

Code: Select All $ ./if_else.sh
Directory does not exists
$ mkdir BashScripting
$ ./if_else.sh
Directory exists

9.2 Nested if-otherwise conditions

#! / bin / bash
# Declare a variable with the value 4
choice = 4
# Displaying
echo "1. Bash "
echo "2. Scripting "
echo "3. Tutorial "

# Execute until variable is four
# Looping
while [$ choice -eq 4]; do

# read user input
read choice
# nested if-otherwise condition
if [$ choice -eq 1]; then

echo "You have chosen word: Bash"

if [$ choice -eq 2]; then
echo "You have chosen word: Scripting"
else

if [$ choice -eq 3]; then
echo "You have chosen word: Tutorial"
else
echo "Please make a choice between 1-3!"
echo "1. Bash "
echo "2. Scripting "
echo "3. Tutorial "
echo -n “Please choose a word? "
choice = 4
fi
fi
fi
done

Code: Select all $ ./nested.sh
1. Bash
2. Scripting
3. Tutorial

5

1. Bash
2. Scripting
3. Tutorial
Please choose a word?
4
Please make a choice between 1-3!
1. Bash
2. Scripting
3. Tutorial
Please choose a word?
3
You have chosen word: Tutorial

Thus, at first, the body of the "while" loop is executed, since the variable choice is initially equal to four. Then we read the user input into it, and if the input is not equal to 1.2 or 3, then we make our variable equal to 4 again, in connection with which the body of the loop is repeated (again it is necessary to enter 1.2 or 3).

10. Comparisons
10.1 Arithmetic comparisons

Lt<
-gt>
-le<=
-ge> =
-eq ==
-ne! =

#! / bin / bash

NUM1 = 2
NUM2 = 2
if [$ NUM1 -eq $ NUM2]; then
echo "Both Values ​​are equal"
else
echo "Values ​​are NOT equal"
fi

Code: Select All $ ./equals.sh
Both Values ​​are equal

#! / bin / bash
# Declare variables with integer values
NUM1 = 2
NUM2 = 3
if [$ NUM1 -eq $ NUM2]; then
echo "Both Values ​​are equal"
else
echo "Values ​​are NOT equal"
fi

Code: Select All $ ./equals.sh
Values ​​are NOT equal

#! / bin / bash
# Declare variables with integer values
NUM1 = 2
NUM2 = 1
if [$ NUM1 -eq $ NUM2]; then
echo "Both Values ​​are equal"
elif [$ NUM1 -gt $ NUM2]; then
echo "$ NUM1 is greater then $ NUM2"
else
echo "$ NUM2 is greater then $ NUM1"
fi

Code: Select All $ ./equals.sh
2 is greater then 1

10.2 Symbolic-Text Comparisons

The same
! = not the same
< меньще чем
> more than
-n s1 variable s1 is not empty
-z s1 variable s1 is empty

#! / bin / bash

S1 = "Bash"

S2 = "Scripting"
if [$ S1 = $ S2]; then

else
echo "Strings are NOT equal"
fi

Code: Select All $ ./statement.sh
Strings are NOT equal

#! / bin / bash
# Declare the symbolic variable S1
S1 = "Bash"
# Declare the symbolic variable S2
S2 = "Bash"
if [$ S1 = $ S2]; then
echo "Both Strings are equal"
else
echo "Strings are NOT equal"
fi

Code: Select All $ ./statement.sh
Both Strings are equal

11. Checking files

B filename Block special file
-c filename Special character file
-d directoryname Check for directory existence
-e filename Check for file existence
-f filename Check for regular file existence not a directory
-G filename Check if file exists and is owned by effective group ID.
-g filename true if file exists and is set-group-id.
-k filename Sticky bit
-L filename Symbolic link
-O filename True if file exists and is owned by the effective user id.
-r filename Check if file is a readable
-S filename Check if file is socket
-s filename Check if file is nonzero size
-u filename Check if file set-ser-id bit is set
-w filename Check if file is writable
-x filename Check if file is executable

#! / bin / bash
file = "./ file"
if [-e $ file]; then
echo "File exists"
else
echo "File does not exists"
fi

Code: Select All $ ls
file.sh
$ ./file.sh
File does not exists
$ touch file
$ ls
file file.sh
$ ./file.sh
File exists

Likewise for the example, we can use the "while" loops to check if the file does not exist. This script will sleep while the file does not exist. Note the Bash negator "!" which negates (inverts) the -e option.

12. Cycles
12.1. For loop

#! / bin / bash
# for loop
for f in $ (ls / var /); do
echo $ f
done

Running a for loop from the bash command line:

Code: Select everything $ for f in $ (ls / var /); do echo $ f; done Code: Select everything $ for f in $ (ls / var /); do echo $ f; done
backups
cache
crash
games
lib
local
lock
log
mail
opt
run
spool
tmp
www

12.2. While loop

#! / bin / bash
COUNT = 6
# while loop
while [$ COUNT -gt 0]; do

let COUNT = COUNT-1
done

Code: Select all $ ./while_loop.sh
Value of count is: 6
Value of count is: 5
Value of count is: 4
Value of count is: 3
Value of count is: 2
Value of count is: 1

12.3. Until loop

#! / bin / bash
COUNT = 0
# until loop
until [$ COUNT -gt 5]; do
echo Value of count is: $ COUNT
let COUNT = COUNT + 1
done

Code: Select All $ ./until_loop.sh
Value of count is: 0
Value of count is: 1
Value of count is: 2
Value of count is: 3
Value of count is: 4
Value of count is: 5

12.4. Loops with implicit conditions
In the following example, the condition for a while loop is the presence of standard input.
The body of the loop will execute as long as there is something to be redirected from standard output to the read command.

#! / bin / bash
# This script will search for and remove spaces
# in files, replacing them with underscores
DIR = "."
Controlling a loop with a read command by redirecting output in a loop.
find $ DIR -type f | while read file; do
# use the POSIX class [: space:] to find spaces in filenames
if [["$ file" = * [[: space:]] *]]; then
# replace spaces with underscores
mv "$ file" `echo $ file | tr '' '_' '
fi;
done

Code: Select All $ ls -1
script.sh
$ touch "file with spaces"
$ ls -1
file with spaces
script.sh
$ ./script.sh
$ ls -1
file_with_spaces
script.sh

13. Functions

#! / bin / bash
# Functions can be declared in any order
function function_B (
echo Function B.
}
function function_A (
echo $ 1
}
function function_D (
echo Function D.
}
function function_C (
echo $ 1
}
# Calling functions
# pass parameter to function function A
function_A "Function A."
function_B
# pass parameter to function function C
function_C "Function C."
function_D

Code: Select All $ ./functions.sh
Function A.
Function B.
Function C.
Function D.

14. Operator selection - Select

#! / bin / bash
PS3 = ’Choose one word:’
# select
select word in "linux" "bash" "scripting" "tutorial"
do
echo "The word you have selected is: $ word"
# Abort, otherwise the loop will be infinite.
break
done
exit 0

Code: Select All $ ./select.sh
1) linux
2) bash
3) scripting
4) tutorial
Choose one word: 4
The word you have selected is: tutorial

15. Operator of choice - Case

#! / bin / bash
echo "What is your preferred programming / scripting language"
echo "1) bash"
echo "2) perl"
echo "3) phyton"
echo "4) c ++"
echo "5) I do not know!"
read case;
# simple case selection structure
# note that in this example $ case is just a variable
# and does not have to be called that. This is just an example
case $ case in
1) echo "You selected bash" ;;
2) echo "You selected perl" ;;
3) echo "You selected phyton" ;;
4) echo "You selected c ++" ;;
5) exit
esac

Code: Select All $ ./case.sh
What is your preferred programming / scripting language
1) bash
2) perl
3) phyton
4) c ++
5) I do not know!
4
You selected c ++

———————————————————————————-

More detailed information can be obtained from various sources, for example from here
original: https://www.linuxconfig.org/Bash_scripting_Tutorial
https://ruslandh.narod.ru/howto_ru/Bash-Prog-Intro/
https://bug.cf1.ru/2005-03-17/programmin ... -book.html

https://ubuntologia.ru/forum/viewtopic.php?f=109&t=2296