Pull to refresh

Немного про Bash и смежные науки. Часть 1

Reading time5 min
Views1.6K
Если вы активно используете Linux для администраторских задач, то наверняка заглядываете время от времени в консоль (или живёте в ней). Несмотря на активное вытеснение текстового интерфейса графическим, а тыкать галочки и нажимать на кнопочки всё-таки интуитивнее, что породило целое поколение эникейщиков, консоль была, есть и будет эффективным средством общения с компьютером. Данная статья рассчитана на тех, кто уже как бы знаком с Bash (Bourne-again Shell), самой популярной реализацией командной оболочки. Этот терминал уже много лет используется по умолчанию чуть ли не в каждом дистрибутиве Linux, так что новички даже не догадываются, что бывают и другие оболочки. Bash пронизан мудростью наших UNIX-предков и всячески рекомендуется для освоения. Сейчас вы увидите, что консоль бывает полезна не только для команд вида «sudo /etc/rc.d/network restart» :)

Псевдонимы


Трёхэтажные команды выглядят очень круто, но набирать их каждый раз утомительно. Так вот Bash позволяет создавать краткие произвольные псевдонимы любому набору команд. К примеру, можно создать команду-псевдоним «la», которая будет запускать «ls -a».

alias la='ls -a'

А чтобы при перезагрузке ваши новые настройки не потерялись, запишите псевдонимы в файл ~/.bash_aliases.

Условные операторы


Всем, кто знаком хотя бы с основами программирования, знакомо понятие условных операторов типа if then else. Bash хоть и не является языком программирования, но допускает использование таких операторов, что невероятно удобно и позволяет избежать использования языков вроде Perl или Python в простых задачах. Вот например:

if uname -a | grep "GNU/Linux" > /dev/null; then echo "Вы работаете в Linux"; fi

Работает это следующим образом: сначала выполняется команда «uname -a», которая получает информацию о вашей системе. Полученная информация просеивается через фильтр «grep», который ищет в ней строку GNU/Linux. Вывод направлен в «dev/null» (чёрная дыра Линукса), потому как нас интересует факт наличия строки, а не её вывод на экран. If, then и fi, как вы уже догадались, и есть условный оператор Bash. «If» проверяет условие, «then» описывает действие, которое соответствует условию, а «fi» просто означает конец логической структуры. Условие может быть любой сложности.

Давайте рассмотрим более полезный пример и проверим запущен ли где-то в системе Firefox. Для этого используем команду «ps aux», а вывод информации перенаправим на фильтр grep. Grep сам является программой, поэтому есть в списке процессов. Поскольку «firefox» содержится в «grep firefox», то окажется, что Firefox якобы есть в процессах, хотя мы запустили всего лишь поиск этой строки. Чтобы обойти неувязочку, используем grep дважды, для фильтрации самого себя :) Запустим его с ключом -v для инвертирования условия:

if ps aux | grep firefox | grep -v grep > /dev/null; then echo "Firefox запущен"; fi

Постоянно набирать такую большую команду неудобно, поэтому сделаем из неё краткий псевдоним:

alias isff='if ps aux | grep firefox | grep -v grep > /dev/null; then echo "Firefox запущен"; fi'

Теперь для проверки нужно лишь выполнить команду isff.

Циклы


Истинная мощь Bash даже не в условных операторах, а в циклах. Циклы используются для многократного повторения некой операции. Рассмотрим на примере:

while (true); do sleep 1; date; done

Команда ежесекундно выводит дату и время на экран, пока не нажмут Ctrl+C. Но это как-то тупо, давайте сделаем что-то более полезное.

Как, например, распаковать несколько архивов tar.bz2 одной командой? А вот так: командой «ls» получаем список bz2-файлов в каталоге и с помощью цикла обрабатываем каждый файл по отдельности. Разумеется, в автоматическом режиме.

for i in `ls *.tar.bz2`; do tar xjf "$i"; done

Обратите внимание на символ обратного апострофа (он расположен на клавиатуре слева от цифры 1). Это оператор, который подставляет результат команды «ls *.tar.bz2» в соответствующее место цикла.

Недооценённый Grep


Обычно Grep используют для решения дебильных задач, вроде таких:

somecommand | grep "fuuu"

То есть для грубой фильтрации вереницы иформации (звучит прям как light amplification by stimulated emission of radiation). Вообще у команды grep огромное количество параметров, но вот самые основные и их стоит запомнить:

-c Подсчитывает число вхождений искомой строки.
-i Поиск, не зависящий от регистра символов.
-l Выводит на экран имена совпавших файлов (это строчная L).
-n Отображает номер соответствующей запросу строки.
-r Выполняет рекурсивный поиск по каталогам.
-v Инвертирует условие поиска (строки, не содержащие цель поиска).


Параметры можно объединять, а grep можно направлять на самого себя. Например, если необходимо подсчитать количество файлов, которые содержат слово «paul» (или «PAUL», «PaUl» и т.д.), кроме тех, которые имеют расширение .txt, вам следует сделать что-то вроде такого:

grep -ilr paul * | grep -cv "\.txt$"

Здесь мы используем важнейшие свойства grep. Комбинация параметров -ilr означает, что выполняется поиск по файлам слов «PAUL», «PaUl» и т.д., поиск проходит рекурсивно по вашей файловой системе, начиная с текущего каталога и возвращает имена подходящих файлов. Всё это поступает на ещё один экземпляр grep, который выполнятся с параметрами -cv, которые, в свою очередь, включают режим подсчёта и поиска файлов, которые не соответствуют регулярному выражению "\.txt$". Обратный слеш здесь экранирует точку, без него мы получили бы специальный символ. А знак доллара означает, что .txt должно находится в конце имени файла. То есть «fuuu.txt.boo» не будет соответствовать выражению.

Не очевидный Find


Команда find не подчиняется законам здравого смысла. То есть не думайте, что можете использовать её в виде «find <иголка> <стог_сена>». В отличие от этого, find работает как фильтр.

find .

Точка в конце означает, что будет возвращён список всех файлов в текущем каталоге. Но команда «ls -a» делает, в принципе, то же самое. Поэтому усложним задачу. Найдём файлы в каталоге, в имени которых есть «arr».

find . -name "*arr*"

А ещё можно добавить параметр "-size" и найти только те файлы, которые больше 1-го мегабайта.

find . -name "*bar*" -size +1M

Параметр "-user" возвращает файлы, принадлежащие указанному пользователю. Например:

find . -name "*bar*" -user veles

Это также полезно использовать с параметром "-not", который, как вы уже догадались, инвертирует поиск:

# все файлы, кроме myfile.txt и тех, которыми владеет veles
find . -not -name "myfile.txt" -not -user veles


Ещё один прикольный фильтр — "-newer". Он возвращает все файлы, которые новее, чем указанный файл. Это очень удобно для скриптов резервного копирования: когда делаете копию, просто укажите произвольный файл, и он будет служить временной меткой, которую можно использовать в команде «find -newer». Таким образом вы получите список всех файлов, которые изменились с момента создания этого файла.

find . -newer /path/to/myfile

Пока достаточно. Разумеется, тонны деталей упущены и остаются вам на самостоятельное изучение. «Маны» ещё никто не отменял, а цель данной статьи — привлечь ваше внимание к великому и могучему UNIX-way.

В следующий раз мы познакомимся с управлением многозадачностью (вы же не забыли, что консоль Линукса многозадачна?), а также подружимся с планировщиком cron, который может стать вашим любимым средством автоматизации рутинной работы.

P.S. Юниксоиды со стажем, скорее всего, давно всё это знают. Но эта статья написана больше для хорошего аппетита интересующихся.
Tags:
Hubs:
Total votes 40: ↑32 and ↓8+24
Comments38

Articles