- •Bash конспект
- •Замечания об этом документе
- •Запуск bash и выход из него. Конфигурационные файлы
- •Символы ";" и "&" -- выполнение нескольких команд
- •Символы "&&" и "||" -- условное выполнение команд
- •Символы ( )
- •Проверка значения арифметического выражения с помощью (( ))
- •Символ !
- •5. Арифметическая подстановка
- •6. Подстановка процесса (bash specific)
- •7. Разбиение на слова
- •8. Path-экспансия
- •9. Удаление кавычек
- •Кавычки и экранирование специальных символов Метасимволы и их экранирование
- •4. Командная подстановка
- •Двойные и одинарные кавычки. Другие виды кавычек
- •Перенаправление
- •Открытие новых дескрипторов
- •Восстановление перенаправленных дескрипторов
- •Закрытие дескриптора
- •Другие внешние команды
- •Информация о пользователях:
- •Информация о системе:
- •Символ !
- •1.2 Что значит "{некоторое странное название команды}"
- •2.5 Как считать со стандартного ввода один символ
- •2.6 Как переименовать все файлы *.Html в *.Htm
- •2.12 Как обратиться к параметру номер I , если I не константа, а переменная?
- •Последняя версия bash
- •Чем bash отличается от sh
Закрытие дескриптора
Закрытие дескриптора осуществляется дублированием его псевдодескриптором " &-":
#!/bin/bash
exec 1>&-
echo
Этот текст никто не увидит
КОМАНДЫ ИЗ НАБОРА SHELL-UTILS
Некоторые из перечисленных здесь команд обычно являются одновременно внешними командами из набора SHELL-UTILS и встроенными командами bash.
Подробное описание команд из этого набора см. в документации к GNU SHELL-UTILS.
команды echo, pwd, test
Внешние команды, echo, pwd и test дублируют встроенные команды bash и немного от них отличаются. Например, встроенная команда BASH echo не воспринимает escape- последовательности как таковые, если не указать специальную опцию "-e".
То есть, если написать 'echo "message1\nmessage2"', bash не заменит "\n" на новую строку, а просто выведет эти символы на экран. Внешняя же команда echo всегда обрабатывает escape- последовательности и не требует ключа "-e".
Чтобы вызвать внешнюю команду вместо встроенной, нужно или указать путь, например "/bin/echo" вместо "echo", или запретить использование некоторой внутренней команды ( enable -n echo) , и тогда bash будет искать внешнюю.
Проверить, дублируется ли некоторая внутренняя команда внешней, можно с помощью " type -a команда".
let
Вычисляет арифметическое выражение и возвращает 0, если оно не равно нулю, и не-0 -- иначе. Среди прочих операций есть присваивание (=) можно присваивать значение переменной. В этом случае имя переменной должно быть без префикса "$", в прочих случаях можно и с "$" и без него.
[ ], test & /usr/bin/test
Проверяет истинность условия (тестирует условие).
Существует в виде как встроенной, так и внешней команды. Если вместо слова test используются квадратные скобки, они обязательно должны быть отделены от аргументов пробелом, потому что на самом деле "[" ≈ это название команды, а " ]" ≈ обязательный последний аргумент этой команды.
Можно комбинировать и отрицать условия:
[ условие1 - a условие2 ] Логическое И
[ условие1 - o условие2 ] Логическое ИЛИ
[ ! условие ] Логическое НЕ
Основные тесты:
-t [ fd ] истина, если file descriptor fd (по умолчанию 0) не перенаправлен
Напр. '! - t 0 ' -- осуществляется ли ввод с клавиатуры
Файлы:
-e file Истина, если существует
-s file Истина, если имеет ненулевой размер
Пустая директория также может иметь ненулевой размер. Поэтому проверять, пуста ли директория, надо примерно так (пример из comp.unix.shell):
dir=${1:-.} # for a standalone script
set -- $dir/.??* $dir/.[!.] $dir/*
case $#$* in
"3$dir/.??* $dir/.[!.] $dir/*")
echo empty ;;
*)
echo not empty ;;
esac
-d file Директория
-f file Обычный файл (не директория)
file1 -ot file2 Старее (older than)
file1 -nt file2 Новее (newer than)
Строки:
-z string Пустая
-n string Не пустая
string1 = string2
string1 != string2
Числа:
arg1 -eq arg2 Равно
также -ne, -lt, -le, -gt, -ge
(not equal, less than, less or equal, greater than etc.)
expr (внешняя команда)
Выводит результат выражения
A == B
A + B
A && B
A || B
length string
substr string index length
match string regexp или string : regexp
Выводит номер символа, с которого начинается совпадение. Если в выражении есть "\(\)", вместо номера печатается часть строки, совпавшая с выражением в скобках.
В отличие от test, expr обычно не является встроенной командой, а имеется только в exe- файле. Часто лучше не использовать! Может замедлить выполнение скрипта в десятки раз. Везде, где это возможно, лучше применять test или let.
Например, вместо:
expr $i + 1 == $n && break
лучше писать:
let i+1==n && break
или:
[ $[$i+1] = "$n" ] && break
tee
Название английской буквы " T". T-shaped pipe splitter.
Перенаправляет вывод стразу во много мест (файлов)
Ключ " -a" заставляет дополнять существующие файлы, а не затирать.
date
Команда date не является командой bash, а входит в набор SHELL-UTILS. Однако представляется нелишним описать ее здесь, ввиду ее исключительной полезности для некоторых задач, традиционно решаемых написанием shell-скриптов, а также потому, что по причине обилия возможностей она имеет довольно нетривиальный синтаксис. Кроме описания, ниже будут даны примеры решения практических задач, связанным с обращением к данным о дате и времени, которые взяты из сообщений в comp.unix.shell
К сожалению, помимо сложного синтаксиса работу с date затрудняет еще и то, что разные реализации date могут иметь опции с одинаковым названием и совершенно разными функциями. Приводимые ниже примеры тестировались на /bin/date из FreeBSD 2.2.5. В некоторых случаях в примерах указаны также отличия этой реализации от date из набора GNU SHELL-UTILS
Формат вывода даты задается например так
date +%d.%m.%y
Ключ -v (-d в GNU date) позволяет напечатать не сегодняшнюю дату, а, например, завтрашнюю:
date -v +1d # /bin/date
date -d "+1 day" # то же для GNU date
или какая была месяц назад :
date -v -1m # /bin/date
date -d "-1 month" # GNU date
Вот такая команда, записанная в скрипте /etc/daily будет копировать каждый день выпуск сегодняшних новостей newsDDMMYY.txt в файл newstoday.txt:
cp `date +news%d%m%y.txt` newstoday.txt
Работа с именами файлов: basename, dirname, pathchk
basename -- имя файла без пути; если в качестве второго документа задать расширение, оно тоже отрезается
dirname -- пусть к файлу без самого имени файла
pathchk -- проверить, допустимо ли имя файла или пути в данной системе
Внимание! Так же как при работе с expr (см.) и другими внешними командами, следует избегать частого применения данных утилит по причине замедления ими работы. dirname и basename без каких либо трудностей можно реализовать с помощью операций над переменными. В следующем примере определяются функции dirname и basename, идентичные по своему поведению одноименным утилитам dirname и basename, и демонстрируется их применение:
basename()
{
local name="${1##*/}"
echo "${name%$2}"
}
dirname()
{
local dir="${1%${1##*/}}"
[ "${dir:=./}" != "/" ] && dir="${dir%?}"
echo "$dir"
}
fullpath=${1:-/dir/file.ext}
name=`basename "$fullpath"`
dir=`dirname "$fullpath"`
echo "file '$name' is located in $dir"
-- выведет:
file 'file.ext' is located in /dir
Для того чтобы всегда вызывать эти функции вместо соответствующих внешних утилит, можно переименовать их в basename и dirname и записать в отдельный файл, например path.sh, а в файлы с использующими эти функции скрипты, добавить ". path.sh" (см. команду "." и source).
Полезными могут также оказаться функции для определения расширения имени файла (назовем ее ext) и имени файла без расширения (namename):
function ext
{
local name=${1##*/}
local name0="${name%.*}"
local ext=${name0:+${name#$name0}}
echo "${ext:-.}"
}
function namename
{
local name=${1##*/}
local name0="${name%.*}"
echo "${name0:-$name}"
}
Обратите внимание на то, что ни одна из показанных выше функций не вызывает других функций из этого же набора, хотя, например, dirname могла бы вызвать basename и отрезать от полного пути полученное из basename значение, однако такой вызов не осуществляется из соображений оптимизации скорости работы этих функций.
