Bash

1. Bash-скрипт Hello World 
Для начала необходимо выяснить, где находится транслятор. Для этого введите следующую команду: 
  1. $ which bash

Откройте ваш любимый текстовый редактор и создайте файл под названием hello_world.sh. В этом файле сохраните следующие строки:
  1. #!/bin/bash
  2. # объявите переменную типа STRING
  3. STRING="Hello World"
  4. #выведите переменную на экран
  5. echo $STRING

Примечание. Каждый bash-скрипт в этом тьюториале начинается с последовательности знаков "#!", который не интерпретируется как комментарий!
Перейдите в директорию, в которую вы сохранили файл hello_world.sh и сделайте этот файл исполняемым:
  1. $ chmod +x hello_world.sh

Ну, теперь вы полностью готовы создать свой первый bash-скрипт:
  1. ./hello_world.sh


2. Простой bash-скрипт для резервного копирования:
  1. #!/bin/bash
  2. tar -czf myhome_directory.tar.gz /home/linuxconfig


3. Переменные
В этом примере мы объявим простую bash-переменную и выведем ее на экран с помощью команды echo.
  1. #!/bin/bash
  2. STRING="HELLO WORLD!!!"
  3. echo $STRING

Скрипт для резервной копии и переменных:
  1. #!/bin/bash
  2. OF=myhome_directory_$(date +%Y%m%d).tar.gz
  3. tar -czf $OF /home/linuxconfig


3.1. Глобальные и локальные переменные
  1. #!/bin/bash
  2. #Объявление глобальной переменной
  3. #Эта переменная глобальна и может быть использована в любом месте скрипта
  4. VAR="global variable"
  5. function bash {
  6. #Объявление локальной переменной
  7. #Эта переменная локальна и может быть использована только в этой функции bash
  8. local VAR="local variable"
  9. echo $VAR
  10. }
  11. echo $VAR
  12. bash
  13. # Обратите внимание, глобальная переменная не изменилась
  14. # "local" это зарезервированное слово в bash
  15. echo $VAR


4. Передача аргументов в bash-скрипт
  1. #!/bin/bash
  2. # используйте ранее определенные переменные для доступа к переданным аргументам to access passed arguments
  3. # аргументы на экран
  4. echo $1 $2 $3 ' -> echo $1 $2 $3'
  5.  
  6. # Мы можем сохранить аргументы из командной строки bash в специальный массив
  7. args=("$@")
  8. # echo arguments to the shell
  9. echo ${args[0]} ${args[1]} ${args[2]} ' -> args=("$@"); echo ${args[0]} ${args[1]} ${args[2]}'
  10.  
  11. # используйте $@ для вывода сразу всех аргументов
  12. echo $@ ' -> echo $@'
  13.  
  14. # используйте переменную $# для вывода
  15. # числа переданных в bash-скрипт переменных
  16. echo Number of arguments passed: $# ' -> echo Number of arguments passed: $#'
  17. /arguments.sh Bash Scripting Tutorial


5. Исполнение команд shell с помощью bash
  1. #!/bin/bash
  2. # используйте обратные кавычки " ` ` " для исполнения команд shell
  3. echo `uname -o`
  4. # исполнение bash-команд вызывается без кавычек
  5. echo uname -o


6. Чтение введенных пользователем данных
  1. #!/bin/bash
  2. echo -e "Hi, please type the word: \c "
  3. read word
  4. echo "The word you entered is: $word"
  5. echo -e "Can you please enter two words? "
  6. read word1 word2
  7. echo "Here is your input: \"$word1\" \"$word2\""
  8. echo -e "How do you feel about bash scripting? "
  9. # команда read сохраняет ответы в дефолтную переменную$REPLY
  10. read
  11. echo "You said $REPLY, I'm glad to hear that! "
  12. echo -e "What are your favorite colours ? "
  13. # -a позволяет команде read сохранять несколько значений в массив
  14. read -a colours
  15. echo "My favorite colours are also ${colours[0]}, ${colours[1]} and ${colours[2]}:-)"


7. Bash-команда trap
  1. #!/bin/bash
  2. # команда trap
  3. trap bashtrap INT
  4. # bash-команда очистки экрана
  5. clear;
  6. # bash функция trap исполняется, когда нажимается CTRL-C
  7. # bash выводит сообщение => Executing bash trap !
  8. bashtrap()
  9. {
  10. echo "CTRL+C Detected !...executing bash trap !"
  11. }
  12. # для значений от 1/10 до 10/10
  13. for a in `seq 1 10`; do
  14. echo "$a/10 to Exit."
  15. sleep 1;
  16. done
  17. echo "Exit Bash Trap Example!!!"


8. Массивы
8.1. Объявление простого bash-массива
  1. #!/bin/bash
  2. # объявление массива из 3 элементов
  3. ARRAY=( 'Debian Linux' 'Redhat Linux' 'Ubuntu Linux' )
  4. # получение числа элементов массива
  5. ELEMENTS=${#ARRAY[@]}
  6.  
  7. # вывод каждого элемента массива
  8. # при заданном диапазоне номеров элементов
  9. for (( i=0;i<$ELEMENTS;i++)); do
  10. echo ${ARRAY[${i}]}
  11. done


8.2. Импорт файла в массив bash
  1. #!/bin/bash
  2. # объявление массива
  3. declare -a ARRAY
  4. # вывести filedescriptor 10 в stdin
  5. exec 10<&0
  6. # stdin заменяется файлом, указанным в качестве первого аргумента
  7. exec < $1
  8. let count=0
  9.  
  10. while read LINE; do
  11.  
  12. ARRAY[$count]=$LINE
  13. ((count++))
  14. done
  15.  
  16. echo Number of elements: ${#ARRAY[@]}
  17. # вывод содержимого массива
  18. echo ${ARRAY[@]}
  19. # вывод stdin из filedescriptor 10
  20. # и закрыть filedescriptor 10
  21. exec 0<&10 10<&-


Исполнение bash-скрипта с выводом в файл execution with an output:
  1. linuxconfig.org $ cat bash.txt
  2. Bash
  3. Scripting
  4. Tutorial
  5. Guide
  6. linuxconfig.org $ ./bash-script.sh bash.txt
  7. Number of elements: 4
  8. Bash Scripting Tutorial Guide
  9. linuxconfig.org $


9. Bash-скрипты с if / else / fi
9.1. Простое Bash-выражение с if/else
Обратите внимание на пробелы в скобках [ и ]! Без этих пробелов, скрипт работать не будет.
  1. #!/bin/bash
  2. directory="./BashScripting"
  3.  
  4. # bash проверка существования директории
  5. if [ -d $directory ]; then
  6. echo "Directory exists"
  7. else
  8. echo "Directory does not exists"
  9. fi


9.2. Встроенный if/else
  1. #!/bin/bash
  2. # объявление выбранной переменной и присваивание ей значения 4
  3. choice=4
  4. # Вывод на stdout
  5. echo "1. Bash"
  6. echo "2. Scripting"
  7. echo "3. Tutorial"
  8. echo -n "Please choose a word [1,2 or 3]? "
  9. # Повторение цикла, пока переменная равна 4
  10. # bash цикл while
  11. while [ $choice -eq 4 ]; do
  12. # чтение введенного значения
  13. read choice
  14. # bash nested if/else
  15. if [ $choice -eq 1 ] ; then
  16. echo "You have chosen word: Bash"
  17.  
  18. else
  19.  
  20. if [ $choice -eq 2 ] ; then
  21. echo "You have chosen word: Scripting"
  22. else
  23. if [ $choice -eq 3 ] ; then
  24. echo "You have chosen word: Tutorial"
  25. else
  26. echo "Please make a choice between 1-3 !"
  27. echo "1. Bash"
  28. echo "2. Scripting"
  29. echo "3. Tutorial"
  30. echo -n "Please choose a word [1,2 or 3]? "
  31. choice=4
  32. fi
  33. fi
  34. fi
  35. done


10. Bash сравнения
10.1. Арифметические сравнения
-lt <
-gt >-le <=
-ge >=
-eq ==
-ne !=

  1. #!/bin/bash
  2. # объявление целочисленных переменных
  3. NUM1=2
  4. NUM2=2
  5. if [ $NUM1 -eq $NUM2 ]; then
  6. echo "Both Values are equal"
  7. else
  8. echo "Values are NOT equal"
  9. fi


  1. #!/bin/bash
  2. # объявление целочисленных переменных
  3. NUM1=2
  4. NUM2=1
  5. if [ $NUM1 -eq $NUM2 ]; then
  6. echo "Both Values are equal"
  7. else
  8. echo "Values are NOT equal"
  9. fi


  1. #!/bin/bash
  2. # объявление целочисленных переменных
  3. NUM1=2
  4. NUM2=1
  5. if [ $NUM1 -eq $NUM2 ]; then
  6. echo "Both Values are equal"
  7. elif [ $NUM1 -gt $NUM2 ]; then
  8. echo "NUM1 is greater then NUM2"
  9. else
  10. echo "NUM2 is greater then NUM1"
  11. fi


10.2. Сравнение строк
= equal
!= not equal
< less then
> greater then
-n s1 string s1 is not empty
-z s1 string s1 is empty

  1. #!/bin/bash
  2. #Объявление строки S1
  3. S1="Bash"
  4. #Объявление строки S2
  5. S2="Scripting"
  6. if [ $S1 = $S2 ]; then
  7. echo "Both Strings are equal"
  8. else
  9. echo "Strings are NOT equal"
  10. fi


  1. #!/bin/bash
  2. #Объявление строки S1
  3. S1="Bash"
  4. #Объявление строки S2
  5. S2="Bash"
  6. if [ $S1 = $S2 ]; then
  7. echo "Both Strings are equal"
  8. else
  9. echo "Strings are NOT equal"
  10. fi


11. Bash проверка файла
-b filename - блокирование файла
-c filename - файл содержит спец. символы
-d directoryname - проверка существования директории
-e filename - проверка существования файла
-f filename - проверка существования НЕдиректории
-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 - проверка доступности файла
-S filename Check if file is socket
-s filename - проверка того, что размер файла больше нуля
-u filename Check if file set-ser-id bit is set
-w filename - проверка перезаписываемости файла
-x filename - проверка исполняемости файла
  1. #!/bin/bash
  2. file="./file"
  3. if [ -e $file ]; then
  4. echo "File exists"
  5. else
  6. echo "File does not exists"
  7. fi

Аналогично для проверки существования файла можно использоватьe цикл while. Этот скрипт не будет работать, пока файл существует. Обратите внимание на bash оператор отрицания "!", который отрицает функцию -e.
  1. #!/bin/bash
  2. while [ ! -e myfile ]; do
  3. # Не реагировать, пока файл создан и существует
  4. sleep 1
  5. done


12. Цикл
12.1. Bash команда зацикливания
  1. #!/bin/bash
  2.  
  3. # bash цикл
  4. for f in $( ls /var/ ); do
  5. echo $f
  6. done

Запуск цикла из командной строки bash:
  1. $ for f in $( ls /var/ ); do echo $f; done


12.2. Bash цикл while 
  1. #!/bin/bash
  2. COUNT=6
  3. # bash цикл while
  4. while [ $COUNT -gt 0 ]; do
  5. echo Value of count is: $COUNT
  6. let COUNT=COUNT-1
  7. done


12.3. Bash цикл until
  1. #!/bin/bash
  2. COUNT=0
  3. # bash цикл until
  4. until [ $COUNT -gt 5 ]; do
  5. echo Value of count is: $COUNT
  6. let COUNT=COUNT+1
  7. done


12.4. Контролирование цикла bash
Ниже представлен пример цикла while, контролируемого стандартным вводом. Bash цикл while работает, пока существует переход от STDOUT к STDIN и к команде read.
  1. #!/bin/bash
  2. # этот bash скрипт найдет и заменит пробелы
  3. # в именах файлов
  4. DIR="."
  5. # контролирование цикла с помощью bash команды read путем перенаправления STDOUT к
  6. # STDIN в цикле while
  7. # команда find не будет отбрасывать имена файлов, содержащие пробелы
  8. find $DIR -type f | while read file; do
  9. # использование POSIX class [:space:] для поиска пробела в имени файла
  10. if [[ "$file" = *[[:space:]]* ]]; then
  11. # замена пробела символом "_" и, следовательно, переименование файла
  12. mv "$file" `echo $file | tr ' ' '_'`
  13. fi;
  14. # конец цикла while
  15. done


13. Функции Bash
  1. #!/bin/bash
  2. # функции Bash могут объявляться в любом порядке
  3. function function_B {
  4. echo Function B.
  5. }
  6. function function_A {
  7. echo $1
  8. }
  9. function function_D {
  10. echo Function D.
  11. }
  12. function function_C {
  13. echo $1
  14. }
  15. # вызов функций
  16. # передача параметра функции А
  17. function_A "Function A."
  18. function_B
  19. # передача параметра функции С
  20. function_C "Function C."
  21. function_D


14. Bash выделение
  1. #!/bin/bash
  2. PS3='Choose one word: '
  3.  
  4. # bash select
  5. select word in "linux" "bash" "scripting" "tutorial"
  6. do
  7. echo "The word you have selected is: $word"
  8. # остановка цикла, иначе он станет бесконечным
  9. break
  10. done
  11.  
  12. exit 0


15. Переключатель
  1. #!/bin/bash
  2. echo "What is your preferred programming / scripting language"
  3. echo "1) bash"
  4. echo "2) perl"
  5. echo "3) python"
  6. echo "4) c++"
  7. echo "5) I do not know !"
  8. read case;
  9. # структура простого bash условия
  10. # обратите внимание: в этом случае $case -это переменная, которая не обязана так называться
  11. # здесь она названа так для примера
  12. case $case in
  13. 1) echo "You selected bash";;
  14. 2) echo "You selected perl";;
  15. 3) echo "You selected python";;
  16. 4) echo "You selected c++";;
  17. 5) exit
  18. esac


16. Кавычки в Bash
Кавычки являются важным элементом языка bash и bash скриптов. Ниже вы найдете некоторые основы использования кавычек в bash.
16.1. Экранирование специальных символов
Перед тем, как мы приступим к использованию кавычек, нам необходимо узнать, как экранировать специальные символы. Эта процедура позволит bash напрямую распознать значение этих символов. Для этого нам нужно использовать обратный слеш "\". Например:
  1. #!/bin/bash
  2. # объявление bash переменной типа string
  3. BASH_VAR="Bash Script"
  4.  
  5. # вывод переменной BASH_VAR
  6. echo $BASH_VAR
  7.  
  8. # если спецсимвол "$" экранирован символом "\", он может быть напрямую распознан
  9. echo \$BASH_VAR
  10.  
  11. # у обратного слеша также есть специальное значение, и оно может быть раскрыто с помощью еще одного слеша "\"
  12. echo "\\"


16.2. Одинарные кавычки
Одинарные кавычки в bash экранируют значение всех специальных символов. Таким образом, специальные символы будут распознаны буквально. При этом нельзя использовать одинарную кавычку внутри двух дургих таких же кавычек, даже если какая-то из них экранирована обратным слешем.
  1. #!/bin/bash
  2. # объявление bash переменной типа string
  3. BASH_VAR="Bash Script"
  4. # вывод переменной BASH_VAR
  5. echo $BASH_VAR
  6. # значение спец. символов в bash экранируется при использовании одинарных кавычек
  7. echo '$BASH_VAR "$BASH_VAR"'


16.3. Двойные кавычки
Двойные кавычки используются в bash для экранирования всех специальных символов, кроме "$", "\" и "`". Все остальные спец. символы будут распознаваться буквально. В отличие от предыдущего пункта, внутри двойных кавычек можно использовать одинарную. Если между двойными кавычками нужно использовать еще одну двойную кавычку, можно заставить bash распознать их буквально, используя обратный слеш "\". Например:
  1. #!/bin/bash
  2. # объявление bash переменной типа string
  3. BASH_VAR="Bash Script"
  4.  
  5. # echo variable BASH_VAR
  6. echo $BASH_VAR
  7.  
  8. # спец. символ и его значение экранируется
  9. # при использовании двойных кавычек вместно "$", "\" и "`"
  10.  
  11. echo "It's $BASH_VAR and \"$BASH_VAR\" using backticks: `date`"


16.4. Bash экранирование ANSI-C
В bash существует также еще один вид экранирования - ANSI-C. При использовании этого типа экранирования, символы, обозначенные обратным слешем "\" получают специальное значение в соответствии со стандартом ANSI-C.
\a alert (bell)
\b backspace
\e an escape character
\f form feed
\n newline
\r carriage return
\t horizontal tab
\v vertical tab
\\ backslash
\` single quote
\nnn octal value of characters ( see [http://www.asciitable.com/ ASCII table] )
\xnn hexadecimal value of characters ( see [http://www.asciitable.com/ ASCII table] )

Обозначение ansi-c bash-экранирования: $'' . Пример:
  1. #!/bin/bash
  2. # для примера мы использовали \n для новой строки, \x40 для шестнадцатеричного значения @
  3. # и \56 для восьмеричного значения .
  4. echo $'web: www.linuxconfig.org\nemail: web\x40linuxconfig\56org'


17. Арифметические операции
17.1. Пример сложения с помощью bash
  1. #!/bin/bash
  2. let RESULT1=$1+$2
  3. echo $1+$2=$RESULT1 ' -> # let RESULT1=$1+$2'
  4. declare -i RESULT2
  5. RESULT2=$1+$2
  6. echo $1+$2=$RESULT2 ' -> # declare -i RESULT2; RESULT2=$1+$2'
  7. echo $1+$2=$(($1 + $2)) ' -> # $(($1 + $2))'


17.2. Арифметика в bash
  1. #!/bin/bash
  2. echo '### let ###'
  3. # bash сложение
  4. let ADDITION=3+5
  5. echo "3 + 5 =" $ADDITION
  6.  
  7. # bash вычитание
  8. let SUBTRACTION=7-8
  9. echo "7 - 8 =" $SUBTRACTION
  10.  
  11. # bash умножение
  12. let MULTIPLICATION=5*8
  13. echo "5 * 8 =" $MULTIPLICATION
  14.  
  15. # bash деление
  16. let DIVISION=4/2
  17. echo "4 / 2 =" $DIVISION
  18.  
  19. # bash modulus
  20. let MODULUS=9%4
  21. echo "9 % 4 =" $MODULUS
  22.  
  23. # bash возведение в степень
  24. let POWEROFTWO=2**2
  25. echo "2 ^ 2 =" $POWEROFTWO
  26.  
  27.  
  28. echo '### Bash Arithmetic Expansion ###'
  29. # существуют два формата обозначения арифметических выражений: $[ выражение ]
  30. # и $(( выражение #)) - вы можете выбирать тот, который вам нравится больше
  31.  
  32. echo 4 + 5 = $((4 + 5))
  33. echo 7 - 7 = $[ 7 - 7 ]
  34. echo 4 x 6 = $((3 * 2))
  35. echo 6 / 3 = $((6 / 3))
  36. echo 8 % 7 = $((8 % 7))
  37. echo 2 ^ 8 = $[ 2 ** 8 ]
  38.  
  39. echo '### Declare ###'
  40. echo -e "Please enter two numbers \c"
  41. # распознавание ввода
  42. read num1 num2
  43. declare -i result
  44. result=$num1+$num2
  45. echo "Result is:$result "
  46.  
  47. # bash конвертация бинарного числа 10001
  48. result=2#10001
  49. echo $result
  50.  
  51. # bash конвертация восьмеричного числа 16
  52. result=8#16
  53. echo $result
  54.  
  55. # bash конвертация шестнадцатеричного числа 0xE6A
  56. result=16#E6A
  57. echo $result


17.3. Округление числа с плавающей точкой
  1. #!/bin/bash
  2. # получение числа с плавающей точкой
  3. floating_point_number=3.3446
  4. echo $floating_point_number
  5. # округление числа с плавающей точкой с помощью bash
  6. for bash_rounded_number in $(printf %.0f $floating_point_number); do
  7. echo "Rounded number with bash:" $bash_rounded_number
  8. done


17.4. Bash вычисления с плавающей точкой
  1. #!/bin/bash
  2. # реализация простого калькулятора в linux на bash
  3. echo "Enter input:"
  4. read userinput
  5. # вывод результата с двумя знаками после запятой
  6. echo "Result with 2 digits after decimal point:"
  7. echo "scale=2; ${userinput}" | bc
  8. # вывод результата с десятью знаками после запятой
  9. echo "Result with 10 digits after decimal point:"
  10. echo "scale=10; ${userinput}" | bc
  11. # вывод результата в виде округленного целого числа
  12. echo "Result as rounded integer:"
  13. echo $userinput | bc


18. Перенаправления
18.1. STDOUT из bash скрипта в STDERR
  1. #!/bin/bash
  2. echo "Redirect this STDOUT to STDERR" 1>&2

Для проверки перенаправления STDOUT в STDERR можно перенаправить вывод скрипта в файл:

18.2. STDERR из bash скрипта в STDOUT
  1. #!/bin/bash
  2. cat $1 2>&1

Для проверки перенаправления STDERR iв STDOUT можно перенаправить вывод скрипта в файл:

18.3. STDOUT на экран 
Простым способом перенаправления STDOUT является простое использование любой команды, поскольку по умолчанию STDOUT автоматически выводится на экран. Но для начала создайте файл "file1":
  1. $ touch file1
  2. $ ls file1
  3. file1

Как вы можете увидеть из вышеприведенного примера, выполнение команды ls вызывает STDOUT, который по умолчанию выводится на экран.

18.4. STDOUT в файл
Чтобы блокировать дефолтное поведение STDOUT, мы можем использовать ">" для перенаправления вывода в файл:
  1. $ ls file1 > STDOUT
  2. $ cat STDOUT
  3. file1


18.5. STDERR в файл
По умолчанию, STDERR выводится на экран:
  1. $ ls
  2. file1 STDOUT
  3. $ ls file2
  4. ls: cannot access file2: No such file or directory

В следующем примере перенаправим стандартную ошибку ( stderr ) в файл, а stdout - как по умолчанию, на экран. Имейте в виду, что STDOUT выводится на экран, а STDERR записывается в файл под наазванием STDERR:
  1. $ ls
  2. file1 STDOUT
  3. $ ls file1 file2 2> STDERR
  4. file1
  5. $ cat STDERR
  6. ls: cannot access file2: No such file or directory


18.6. STDOUT в STDERR 
Также возможно перенаправление STDOUT и STDERR в один файл. В следующем примере перенаправим STDOUT в тот же дескриптор, что и STDERR. И STDOUT, и STDERR будут перенаправлены в файл "STDERR_STDOUT".
  1. $ ls
  2. file1 STDERR STDOUT
  3. $ ls file1 file2 2> STDERR_STDOUT 1>&2
  4. $ cat STDERR_STDOUT
  5. ls: cannot access file2: No such file or directory
  6. file1

Теперь файл STDERR_STDOUT содержит и STDOUT, и STDERR.

18.7. STDERR to STDOUT
Пример выше можно переделать так, чтобы перенаправлять STDERR в тот же дескриптор, что и SDTOUT:
  1. $ ls
  2. file1 STDERR STDOUT
  3. $ ls file1 file2 > STDERR_STDOUT 2>&1
  4. $ cat STDERR_STDOUT
  5. ls: cannot access file2: No such file or directory
  6. file1


18.8. STDERR и STDOUT в файл
Оба верхних примера перенаправляли STDOUT и STDERR в файл. Существует и другой способ добиться того же эффекта:
  1. $ ls
  2. file1 STDERR STDOUT
  3. $ ls file1 file2 &> STDERR_STDOUT
  4. $ cat STDERR_STDOUT
  5. ls: cannot access file2: No such file or directory
  6. file1

or
  1. ls file1 file2 >& STDERR_STDOUT
  2. $ cat STDERR_STDOUT
  3. ls: cannot access file2: No such file or directory
  4. file1