Bash скрипты
При запуске скрипта создается дочерняя консоль, в ней выполняется скрипт и результат возвращается в консоль.
Можно запускать через source, имя (если . в PATH), ./... , и ./ ... & С фоновой задачей аккуратно с объемом вывода, ^C не работает.
Shebang
Лучше использовать shebang в начале (указатель, какую консоль использовать)
#!/bin/bash
#!/bin/bash -x | Выводит все команды во время исполнения |
#!/bin/bash -r | Блокирует потенциально опасные действия |
Параметры можно указывать при запуске скрипта, тогда shebang работать не будет.
Удобства
Комментарии #
bash -n script.sh проверка синтаксиса без исполнения скрипта
Внутри можно использовать следующую конструкцию для вывода части скрипта:
#!/bin/bash
...
set -x
...potentially error part...
set +x
Операция ; запускает несколько команд независимо от их статуса завершения
ls; ps; whoami
выполнит все команды
Перенаправления результата выполнения
> | Stdout в файл, файл очищается |
>> | Stdout в файл, файл дополняется |
&> or >& | Stdout и Stderr в файл, файл очищается |
&>> | Stdout и Stderr в файл, файл дополняется |
< | Перенаправление ввода в команду |
<< | Перенаправление многострочного ввода в команду |
Номера потоков
0 - stdin, 1 - stdout, 2 - stderr
lzl -l 1> stdout.txt 2>stderr.txt
выведет в stderr.txt
Функции
function functname
{
shell commands
}
functname ( )
{
shell commands
}
Используют позиционные переменные.
functname "one" $7
Если внутри функции нужна локальная переменная, то local var1="something", иначе используется глобальная переменная.
Статус возврата из функции перезаписывается после каждого вызова команды, поэтому при необходимости возврата статуса некоторой функции внутри нужно сохранять статус.
cd baddir
echo $?
По умолчанию возвращается статус вызова последней команды. Либо через return N
builtin mkdir "/var/first"
es=$?
echo "$OLDPWD --> $PWD"
return $es
Желательно возвращать код результата, а не просто цифру.
Программы для работы с функциями
declare | -f список функций с описанием |
-F только имена функций | |
unset fname | удалить функцию из памяти |
type fname | Описание функции |
-t выведет тип |
Приоритет при вызове из консоли
- Aliases
- Служебные слова типа if, ...
- Функции
- Встроенные команды типа cd, type, ...
- Скрипты и исполняемые команды
Переменные
Строковые (по умолчанию)
Описывается $varname или ${varname} Например есть переменная UID. Для вывода 0_ нужно использовать echo ${varname}_
Удаление переменной unset var1
$1, $2, ... | Позиционные параметры |
$* | Строка, содержащая все параметры через пробел |
$@ | Равна N строкам-параметрам. Актуально при передаче в функции. |
$# | Количество аргументов |
var1=$(cmd) | Сохранение результата cmd в переменную |
Определение глобальной переменной: var1="something"
Обработка значений переменных перед вводом
${varname:-word } | Если переменная не существует или существует но пустая - вернет word |
${varname:=word} | Если переменная не существует или существует но пустая - присвоит ей word и вернет word |
${varname:?message} | Если переменная не существует или существует но пустая - выведет сообщение и завершит скрипт |
${varname:+word} | Если переменная существует или пустая - вернет word, иначе null |
${varname:offset:length} |
Срез. count=frogfootman ${count:4} вернет footman ${count:4:4} вернет foot |
Обработка переменных
${var#pattern}
|
Если шаблон совпадает с началом значения переменной - удалить самую короткую часть от начала строки с совпадением и вернуть результат var="/home/user/docs/file.txt" |
${var##pattern} |
var="/home/user/docs/file.txt" echo ${var##*/} # file.txt (отрезано всё до последнего "/") |
${variable%pattern} |
file="archive.tar.gz" echo ${file%.*} # archive.tar |
${variable%%pattern} |
file="archive.tar.gz" echo ${file%%.*} # archive |
${variable/pattern/string} |
Наибольшее совпадение шаблона с переменной заменяется строкой. Первое совпадение |
${variable//pattern/ string} |
Наибольшее совпадение шаблона с переменной заменяется строкой. Все совпадения |
echo -e ${PATH//:/'\n'} выведет разделенное через : значение в значения списком |
Длина значения ${#filename}
Типизированные
При помощи declare <param> var
The variables are treated as arrays Use function names only Display function names without definitions-i The variables are treated as integers
-a | Массив |
-i | Целое число |
-r | Переменная только для чтения |
-x | Переменная экспортируется в окружение |
-f |
Хрень. Возвращает тело функции если она есть.
|
-F | Возвратит имя функции если она есть. |
Пример:
declare -i val3=12 val4=5
declare -i result2
result2=val3*val
echo $result2
Выведет 60
Использование let
let result="4 * 5"
echo $result
Также можно использовать двойные скобки
let result=$((4 * 5))
echo $result
Есть операции +,-,/,*,%-модуль, += увеличение на константу, -=
Массивы
arr = (1 2 3)
echo "${arr[*]}" #весь массив
echo "${arr[0]}" #1
unset ${arr[1]} #удалит 2 из массива
${arr[0]}=10 #перезапишет 1 в 10
Условия
Условия завершения программы
Условие анализируется не на логическом, а на статусе результата (exit status) выполнения программы. 0 - ОК, 1-255 ошибка.
if condition
then
statements
[elif condition
then statements...]
[else
statements]
fi
Условие анализа строк
конструкция [], внутри нее возможны условия проверки и сравнения строк.
str1 = str2 | Строка 1 равна строке 2 |
str1 != str2 | Строка 1 не равна строке 2 |
str1 > str2 str1 < str2 | Больше/меньше |
-n str1 | Строка 1 не пустая |
-z str1 | Строка 1 пустая |
Условия сравнения чисел
-lt | Менее чем |
-le | Меньше или равно |
-eq | Равно |
-ge | Больше или равно |
-gt | Больше |
-ne | Не равно |
Можно комбинировать
if command && [ condition ]; then
Логика внутри условия
&& или -a |
Выполнить команду 1, если статус 0 - выполнить команду 2
|
|| или -o |
Выполнить команду 1, если статус не 0 - выполнить команду 2
|
! |
Отрицание |
Свойства файла, проверяемые в условиях
-a file, -e file | Файл существует |
-d file | Директория существует |
-f file | Файл существует и является файлом (не директория или специальный файл) |
-r file, -w file | Есть право чтения файла, Есть право записи в файл, |
-x file | Есть право исполнения файла или право поиска в директории |
-s file | Файл существует и не пустой |
-N file | Файл был изменен с момента последнего чтения |
-O file, -G file | Запустивший скрипт является владельцем файла, Группа запустившего скрипт входит в группу файла |
file1 -nt file2 | file1 новее file2 (сравниваются время модификации) |
file1 -ot file2 | file1 старее file2 (сравниваются время модификации) |
Цикл for
Итерируется только по полному списку.
for name [in list]
do
statements that can use $name...
done
Если list не определен, то используется $@
Есть переменная IFS
IFS=:
for dir in $PATH
do
ls -ld $dir
done
Цикл while
while condition do
statements...
done
Цикл until
until command; do
statements...
done
Case
for filename in "$@"; do
pnmfile=${filename%.*}.ppm
case $filename in
*.jpg ) exit 0 ;;
*.tga ) tgatoppm $filename > $pnmfile ;;
*.xpm ) xpmtoppm $filename > $pnmfile ;;
*.pcx ) pcxtoppm $filename > $pnmfile ;;
*.tif ) tifftopnm $filename > $pnmfile ;;
*.gif ) giftopnm $filename > $pnmfile ;;
* ) echo "procfile: $filename is an unknown graphics file."
exit 1 ;;
esac
outfile=${pnmfile%.ppm}.new.jpg
pnmtojpeg $pnmfile > $outfile
rm $pnmfile
done
Опции исполнения
shift смещает переменные влево.
myshift.sh
echo $1 $2
shift
echo $1 $2
Использование: ./myshift.sh one two
Вывод:
one two
two
Вариант 1,скрипта, считывающего параметры со случайным размещением параметров
while [ -n "$(echo $1 | grep '-')" ]; do
case $1 in
-a ) aopt=$2
shift;;
-b ) bopt="True"
;;
-c ) copt=$2
shift;;
* ) echo 'usage: alice [-a] [-b] [-c] args...'
exit 1
esac
shift
done
Опция -b является одинарной, -a и -c параметризованные.
В процессе исполнения можно добавлять интерактивность за счет считывания аргументов
echo "First arg"
read -r farg
echo "First arg is ${farg}"