Материалы к спецкурсу "Unix"

Структура файловой системы

В стандартной файловой системе (ФС) ОС Unix могут храниться объекты нескольких типов:

  • обычные файлы
  • каталоги
  • символические ссылки
  • специальные файлы - точки доступа к драйверам устройств
  • коммуникационные объекты FIFO
  • сокеты UNIX

Все эти объекты используют единую систему имен и имеют идентичные атрибуты, характеризующие права доступа.

Имя файла и его атрибуты (тип объекта, права доступа, информация о его расположении на носителе и т.п.) хранятся независимо друг от друга. Имена хранятся в каталогах, а атрибуты - в специальных структурах - inode.

Для хранения атрибутов файлов в ФС используется массив индексированных узлов inode (Indexed Node). Индекс - это целое число, указывающее порядковый номер inode в массиве. Для каждого файла в пределах одного раздела на диске индекс inode уникален. При этом, на разных дисках или на разных разделах одного диска ведётся своя независимая нумерация inode - так, например, индекс 2 может использоваться для корневого каталога каждого из разделов диска. Для объединения нескольких дисков в единую ФС используется виртуальная файловая система, которая пересчитывает номера inode так, чтобы обеспечивалась их уникальность. Если в Unix используется сторонняя ФС (например FAT или NTFS) то структура inode эмулируется на уровне виртуальной файловой системы.

Связь между именем и атрибутами осуществляется через объекты-каталоги. Каталоги в Unix - это таблицы, хранящие имя файла и индекс inode в массиве атрибутов. Один файл может иметь несколько имен, т.е. в различных каталогах или даже в одном каталоге могут быть записи, связывающие различные имена с одним inode.

Права доступа (R)ead, (W)rite, e(X)ecute определены по отдельности для трех категорий пользователей (U)ser,(G)roup, (O)ther. Дополнительно к правам доступа есть флаг смены владельца на время выполнения файла, смены группы на время выполнения файла и признак «липкости» (sticky bit), что бы он не означал.

Файлы можно создавать (одновременно давая имя), добавлять новые имена, удалять старые имена, а также менять права доступа к файлу (влияет на сам файл, вне зависимости от того к какому из его имен применялась операция). Администратор может еще и поменять владельца файла.

Файл, оставшийся без имени и не используемый для ввода/вывода или в качестве источника данных программы – уничтожается.

Стандартные каталоги UNIX

Во всех Unix-подобных ОС (FreeBSD, Linux, с некоторыми изменениями в Android и MacOS X) используется традиционная схема именования каталогов, которая описывается стандартом Filesystem Hierarchy Standard. В целом структура каталогов представляет из себя дерево с единым корнем, обозначаемым /.

В корневом каталоге находятся следующие подкаталоги:

"Базовые" каталоги, которые для правильного старта системы должны быть доступны в момент загрузки ядра:
/etc – конфигурационные файлы;
/bin – минимальный набор утилит пользователя, необходимых для запуска системы;
/sbin – минимальный набор утилит администратора, необходимых для запуска системы;
/lib – динамические библиотеки для утилит из /bin и /sbin. В Linux в каталоге /lib/modules размещаются модули ядра;
/dev – каталог, содержащий набор специальных файлов устройств – точек доступа к драйверам;
/tmp – каталог для временных файлов;

Дополнительные каталоги:
/root – «домашний» каталог администратора (пользователя root). /usr – основной каталог, содержащий программы, библиотеки, файлы документации и пр.;
/var – каталог для данных большого и часто меняющегося размера – лог-файлов, баз данных, временных файлов печати и почты и пр.;
/opt – каталог для установки коммерческих программ;
/home – каталог для размещения «домашних» каталогов пользователей.

Виртуальные файловые системы в каталогах /proc и /sys предоставляют доступ к переменным ядра ОС, оформленным в виде виртуальных файлов.

Имя каталога /usr произошло от слова User (пользователь) в те времена, когда диски были маленькими и полный комплект программ на них не входил. Каждому пользователю приходилось создавать свой рабочий набор программ на отдельном диске, который и подключался в каталог /usr. В большинстве современных Unix-подобных ОС все стандартные программы размещаются именно в каталоге /usr (Android, скорее, исключение).

В каталоге /usr находятся следующие подкаталоги:
/usr/bin, /usr/sbin, /usr/lib – по аналогии с каталогами в корне;
/usr/include – заголовочные файлы для компиляторов языков C и C++ ;
/usr/share – документация, шрифты, программы на скриптовых языках и другие неизменяемые данные, которые могут быть использованы через сетевую файловую систему с любой версией программ и для любой архитектуры процессора;

/usr/local – каталог для установки программ, не включенных в основную поставку системы. Название получил в то время, когда разработчики Unix'а активно экспериментировали с сетевыми файловыми системами. Считалось, что каталог /usr может быть подключен по сети для всех компьютеров в локальной сети, а /usr/local – расположен на локальном диске. В /usr/local находятся стандартные подкаталоги etc, bin, sbin, lib.

Каталог /var предназначен для хранения больших объемов данных. Иногда его располагают на отдельном большом разделе диска. В /var можно отметить следующие подкаталоги:
/var/log – лог-файлы;
/var/mail – почтовые ящики пользователей;
/var/tmp – общедоступный каталог для временных файлов. В некоторых системах /tmp размещается на маленьком разделе диска, в этом случае /var/tmp - это каталог в котором можно размещать большие временные файлы.

В зависимости от используемой ОС, стадии загрузки системы и прав доступа программе могут быть доступны только некоторые из перечисленных каталогов. Существуют только два элемента файловой системы, которые доступны всегда - каталог /tmp и файл управляющего терминала /dev/tty.

Основные системные команды Unix

Управление файлами и каталогами

ls – список файлов (LiSt). По умолчанию выводится текущий каталог.
Полезные опции: -a – включать файлы с именами, начинающимися с точки; -R – рекурсивно показывать содержимое подкаталогов; -l – вывод подробной информация о файлах:

ls -l dir – подробная информация о файлах в каталоге dir
ls -ld dir – подробная информация о самом каталоге dir

touch file – если файл не существует, то он создается; иначе время модификации файла устанавливается в текущее.

rm file – удалить файл (ReMove).
Полезные опции: -R или -r – рекурсивное удаление каталогов, -i – интерактивные запросы на подтверждение удаления, -f – отмена интерактивного режима.

cp file1 file2 – копирование файла (CoPy) file1 в file2
cp file1 file2 file3 dir – копирование группы файлов в каталог dir
cp -R dir1 dir2 – копирование каталога dir1 со всеми его файлами и подкаталогами в каталог dir2

mv file1 file2 – переименование файла (MoVe);
mv file dir – перемещение файла в каталог dir. Если каталог находится в том же разделе диска, что и файл, то происходит создание новой записи в каталоге без копирования данных. Если файл и каталог находятся в разных разделах, то происходит копирование содержимого файла на новый раздел, после чего старая копия удаляется.

mkdir dir – создать каталог (MaKe DIRectory) с именем dir
rmdir dir – удалить каталог (ReMove DIRectory) dir. Удаление возможно только в том случае, когда каталог пуст.
rm -R dir – рекурсивно удалить каталог со всеми вложенными подкаталогами и файлами.

ln file1 file2 – создать имя (LiNk) file2 для file1
ln -s file1 file2 – создать символическую ссылку с именем file2, указывающую на file1
ln -s /etc/passwd – создать в текущем каталоге символическую ссылку с именем passwd , указывающую на /etc/passwd
ln -s /etc/passwd dir – создать в подкаталоге dir символическую ссылку с именем passwd, указывающую на /etc/passwd
ln -s file dir – ошибка. Подразумевается, что в подкаталоге dir будет создана ссылка с именем file, указывающая на file из текущего каталога. Но в символическую ссылку записывается не объект ФС, а текст, заданный в первом параметре. В результате команды в подкаталоге dir появится ссылка с именем file, ссылающаяся на file, т.е. сама на себя.
ln -s ../file dir – возможный вариант правильного написания предыдущей команды.

Изменение прав доступа к файлам и каталогам

Все команды этой группы с опцией -R могут применяться к каталогу. В этом случае команда применяется к каталогу, а также рекурсивно применяется ко всем файлам и подкаталогам, расположенным внутри этого каталога.

chown user file – смена владельца файла file на user. Команда может выполняться только администратором root.
chgrp group file – смена группы владельцев файла. Для успешного выполнения команды пользователь должен быть членом группы group или администратором root.
chown user:group file – одновременная смена владельца и группы.

chmod u+w file – смена прав доступа к файлу или каталогу. В данном случае добавление владельцу файла права на запись в этот файл. Право доступа может поменять владелец файла или администратор root.

Права доступа к файлу записываются выражением из трех компонентов:

  • Для кого меняются права: u – пользователь (User), g – группа (Group), o – остальные (Other)
  • Операция с правами: + – добавить право, - – удалить право, = – сбросить все существующие права и добавить перечисленные
  • Какие права меняются: r – чтение (Read), w – запись (Write), x – исполнение (eXecute)

Управление процессами

В отличие от команд управления файлами, команды управления процессами могут сильно отличаться в разных ОС. Поэтому приведены версии команд, которые будут работать в ОС Linux.

ps – выдача списка процессов (Process liSt). По умолчанию выдаются процессы, запущенные в текущем сеансе
ps -e – выдача списка всех запущенных процессов (в коммерческих версиях Unix'а и в Linux)
ps ax – выдача списка всех запущенных процессов (FreeBSD и Linux)
ps ax --forest – группировка процессов по признаку родительский процесс/дочерний процесс (только Linux)

kill -KILL 23456 – принудительное завершение процесса с идентификатором (pid) 23456

Программы сжатия и архивирования

Программы сжатия данных gzip, bzip2, xz

Программы gzip, bzip2, xz предназначены для сжатия одиночных файлов. Сжатые файлы имеют расширения .gz, bz2, xz соответственно. Кроме того, распознаются расширения .tgz, .tbz, .txz, являющиеся сокращением от двойных расширений .tar.gz, .tar.bz2, .tar.xz.

Для распаковки используются эти же программы с опцией -d (decompress).

При сжатии файла оригинальный файл удаляется и создается сжатый файл, к имени которого добавляется соответствующее расширение. При распаковке расширение отбрасывается, создается несжатый файл, а сжатый файл удаляется. Исключением являются случаи, когда имя файла не задано, вместо имени файла стоит "-" или дополнительно к имени файла опция -c. В первых двух случаях исходные данные читаются со стандартного ввода, а результат выводится на стандартный вывод, в третьем - исходные данные читаются из файла, файл не удаляется, результат выводится на стандартный вывод.

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

У программ сжатия есть альтернативные имена. Запуск по этим именам эквивалентен запуску с некоторым набором опций.
gunzip, bunzip2, unxz = запуск с опцией -d
zcat, bzcat, xzcat = запуск с опцией -c

Вспомогательные программы:
zmore file.gz = zcat file.gz | more
zgrep file.gz text = zcat file.gz | grep text
zdiff file1.gz file2.gz = zcat file1.gz > /tmp/xxfile1; zcat file2.gz > /tmp/xxfile2; diff /tmp/xxfile1 /tmp/xxfile2; rm /tmp/xxfile1 /tmp/xxfile2

Примеры

Сжатие файла
gzip file

Распаковка файла
gzip -d file.gz

Сжатие "на лету"
echo Test | gzip > test.gz

Распаковка в стандартный вывод и подсчет строк в распакованном потоке
gzip -d -c test.gz | wc -l

Архиватор tar

Архиватор tar (Tape ARchiver) изначально предназначен для создания архивов файлов на магнитных лентах. При архивировании после списка опций указываются имена файлов и каталогов, которые надо поместить в архив. Для того, чтобы указать файл архива, используется опция -f имя_файла (обычного или файла-устройства). Если вместо имени файла указан "-", то для ввода/вывода архива используется стандартный ввод/вывод.

Каждый файл в архиве предваряется заголовком, содержащим имя файла, права доступа, владельца и группу владельцев файла (в текстовом представлении) и другие атрибуты файла. При извлечении файла из архива атрибуты по возможности восстанавливаются.

Основные операции с архивом задаются соответствующими опциями :
– Создать архив (Create)
-t – Проверить архив и выдать список заархивированых файлов (Test)
-x – Извлечь файлы из архива (eXtract)

Дополнительные опции, используемые совместно с опциями операций:
-v – Печатать информацию о процессе архивирования/извлечения файлов
-z – Использовать gzip для дополнительного сжатия/распаковки архива
-j – Использовать bzip2 для дополнительного сжатия/распаковки архива
-J – Использовать xz для дополнительного сжатия/распаковки архива (только последние версии)

Новые версии gnutar умеют при извлечении файлов из архива определять программу сжатия автоматически. Для старых версий требуется явно указывать опцию. Версии tar из коммерческих вариантов Unix вообще не поддерживают опции сжатия и требуют построения конвейера из программы сжатия и архиватора tar.

Опции можно писать без знака минус и писать несколько опций вместе, начиная с опции операции и заканчивая опцией задания файла архива.

Примеры

Заархивировать каталог /etc в архив etc.tar
tar cf etc.tar /etc

Заархивировать каталог /etc в архив etc.tbz, на лету сжимая архив программой bzip2 и выдавая в процессе архивирования имена обрабатываемых файлов
tar cjvf etc.tbz /etc

Выдать содержимое архива etc.tbz
tar tf etc.tbz - современная версия tar
tar tjf etc.tbz - более ранние версии tar

Распаковать архив etc.tgz в современной версии tar
tar xf etc.tgz

Распаковать архив, сжатый программой xz, версией tar без встроенной поддержки этого формата
xzcat etc.txz | tar xf -

Переслать каталог с вложенными файлами и подкаталогами в домашний каталог пользователя user на компьютер remotehos.example, используя программу ssh
tar cf - mydir/ | ssh user@remotehos.example tar xf -

Архиватор cpio

Программа cpio (CoPy In/Out) предназначена для чтения файлов из архива (In) и записи файлов в архив (Out), а также для копирования файлов из каталога в каталог (Pass through). По умолчанию чтение/запись архива производится через стандартный ввод/вывод. Чтобы явно указать файл архива, используется опция -F. В программу встроены средства удаленного протокола через rsh или ssh. Для работы с архивом на удалённой машине он задаётся в формате -F user@host:file. Для администраторов Linux'a программа интересна тем, что с её помощью создаются установочные пакеты формата RPM и образы начальной загрузки initrd.

Основные опции:

cpio -i -d < <archive> – чтение архива со стандартного ввода. Дополнительная опция -d указывает, что надо создавать структуру подкаталогов, сохраненную в архиве.
find . -depth -print0 | cpio -o --null > <archive> – чтение имен файлов со стандартного ввода и вывод архива на стандартный вывод. Опция -print0 команды find и --null команды cpio указывают на то, что в качестве разделителя имён файлов используется нулевой символ '\0'. Это позволяет корректно отработать имена, содержащие пробелы, табуляции и переводы строк.
find . -name z\* -depth -print0 | cpio -p --null -d /tmp – скопировать все файлы с именами на букву z из текущего каталога с подкаталогами в каталог /tmp. Опция -d указывает, что в целевом каталоге надо создавать необходимые подкаталоги.

Просмотр текста командами more и less

Для удобного просмотра текста из файла или со стандартного вывода программы используются программы постраничного пролистывания – "пэйджеры".

more

Простейшая программа для постраничного просмотра текста more используется с именем файла(ов) в качестве параметра или как последняя команда в цепочке перенаправлений ввода/вывода. С помощью опций +<число> или +/<образец текста> можно начать просмотр с интересующей строки.

# Просмотр файла file1 с 20-ой строки
more +20 file1

# Поиск в выводе программы grep подстроки 13:00 и просмотр вывода, начиная с этого места
grep ntpd /var/log/messages | more +/13:00

more умеет листать текст вперёд. Текст из файла, в принципе, можно пролистать назад, но это нетипичное использование more.

Основные интерактивные команды more похожи на команды редактора vi:

  • h – help
  • q – выход
  • SPACE – пролистать один экран
  • d – пролистать пол экрана
  • RETURN – пролистать одну строку
  • /pattern – пролистать до строки содержащей подстроку pattern
  • n – повторить поиск подстроки
  • = – показать номер текущей строки
  • :n – перейти к следующему файлу
  • :p – вернуться к предыдущему файлу
  • :f – напечатать имя текущего файла и номер строки в нем
  • ! – запуск shell-команды

Только при просмотре файлов:

  • b – пролистать экран назад
  • v – вызвать текстовый редактор, установив курсор на текущую строку

less

less – существенно более развитая команда для пролистывания текста. При чтении данных со стандартного ввода она создает буфер, который позволяет листать текст как вперед, так и назад, а также искать как по направлению к концу, так и по направлению к началу текста. Заполнение буфера идет блоками по 64KB, поэтому (если текст на стандартный ввод подается медленно) возможна ситуация "подвисания", когда less показывает очередные поступившие строки, но не позволяет выполнить какую-либо команду.

less понимает все команды more плюс свои.

  • h – вызов справки
  • q – выход
  • SPACE – на экран вперёд
  • b – пролистать экран назад
  • k и j или стрелки вверх и вниз – вертикальная прокрутка по строке
  • g – перейти на 1-ую строку
  • <N>g – перейти на строку N
  • G – перейти на последнюю строку
  • F – перейти на последнюю строку файла и ожидать записи новых строк (аналог tail -f, не работает со стандартным вводом)
  • /pattern – поиск по шаблону вперёд
  • ?pattern – поиск по шаблону назад
  • n – следующее совпадение
  • N – предыдущее совпадение
  • mбуква – отметить позицию буквой
  • 'буква (апостоф и буква) – перейти на отмеченную позицию
  • ! – запуск shell-команды (% – имя текущего файла, к примеру: ! cat % > /tmp/foobar.txt)

Только для файла

  • v – запуск редактора

Только для стандартного ввода

  • s filename – сохранить выводимый текст в файл filename

Параметры вывода текста less можно указывать как в виде опций, так и в интерактивном режиме. Повторный ввод опции в интерактивном режиме отменяет действие.

  • -g – при поиске подсвечивать только текущее найденное слово (по умолчанию подсвечиваются все вхождения)
  • -N – показывать номера строк

Установка программы из исходных текстов

Очень многие программы для Unix, распространяемые в исходных текстах, используют для автоматической настройки под операционную систему средства autoconf и automake. Подобные программы компилируются и устанавливаются типовым образом.

Общепринятая схема сборки программы выглядит так:

  • Скачать архив с программой и необходимые патчи от сторонних разработчиков. Например, с помощью консольной программы скачивания wget
    wget ftp://ftp.chg.ru/prog.tgz
    wget http://home.yandex.ru/prog-my.patch

  • Проверить, что архив распакуется в отдельный каталог. Если архив распаковывается в текущий каталог, то создать рабочий каталог, скопировать архив туда. 1
    tar tzf prog.tgz

  • Распаковать архив
    tar xzf prog.tgz

  • Перейти в каталог с распакованными исходниками
    cd prog

  • Прочитать файлы README и INSTALL :)

  • Применить патч 2
    patch -p1 < ../prog-my.patch

  • Настроить процесс сборки под конкретную ОС
    ./configure

  • Скомпилировать программу
    make

  • Установить в стандартный каталог (требуются права root'а)
    make install


  1. Прочитать про архиватор tar ↩︎

  2. patch -p1 – Как правило, в файлах патча имена представлены в виде пар oldversion/file.c newversion/file.c. Опция -p1 означает, что из имен файлов надо отбросить один уровень каталогов. ↩︎

Утилиты работы с текстом

Unix обладает богатым набором утилит для работы с текстом. Некоторые из них позволяют создать на основе текстовых файлов маленькое подобие базы данных. Все утилиты, рассматриваемые в этом разделе, могут работать как с файлами (наборами файлов), так и со стандартным вводом. Часть утилит может работать с двоичными файлами.

Будем рассматривать текстовые файлы как набор записей-строк, возможно, состоящих из полей, разделённых знаками препинания, слов, разделённых пробелами, и букв.

wc – подсчёт строк, слов и букв. По умолчанию выдаёт все три значения. Интересующую величину можно выбрать с помощью опции -l, -w, -c соответственно.

wc -w /etc/passwd # подсчёт слов в файле passwd
ls | wc -l  # подсчёт числа файлов в текущем каталоге

split – разбиение файла на меньшие, определённого размера. Может разбивать текстовые файлы по строкам и любые – по байтам. По умолчанию читает со стандартного ввода и создает файлы с именами вида xaa, xab и т.д. По умолчанию разбиение идёт по 1000 строк в файле.

cat – объединение файлов. Работает не только с текстовыми файлами, но и с двоичными. Возможно объединение содержимого файлов со стандартным вводом. В этом случае в качестве одного или нескольких имен файлов в командной строке указывается знак -. Пример:

echo "------------" | cat file1 - file2 #Вывод содержимого двух файлов, разделённого строкой из минусов

head – выборка первых строк (байтов) файла:

head -n 12 file  # первые  12 строк
head -c 12 file  # первые  12 байтов
head -n -12 file  # с начала, отбросив 12 строк с конца

tail – выборка последних строк (байтов) файла:

tail -n 12 file  # последние  12 строк
tail -c 12 file  # последние  12 байтов
tail -n +12 file # с 12-ой строки до конца

tail и head – объединение команд обеспечивает выборку диапазона строк:

# 24 строки, начиная с 12-ой (с 12 по 35)
tail -n +12 file | head -n 24
# или
head -n 35 file | tail -n 24

cut – выделение столбца. Довольно неудобная команда, ориентированная на файлы с колонками, разделёнными определённым символом (по умолчанию - символом табуляции), или на файлы с колонками в фиксированных позициях. Опции -f - номер колонки для вывода, -d - символ разделитель. Пример:

# Вывод списка домашних каталогов пользователей (шестое поле в файле passwd)
cut -f6 -d':' /etc/passwd

awk – альтернатива cut. Вообще-то, awk – это довольно развитый язык программирования, но в данном случае нас интересует способность awk разбирать строку на элементы, разделённые пробельными символами. Примеры:

awk '{print $9}' #Вырезание девятой колонки
awk '{print $5 $4 $3 $2 $1}'  #Перестановка местами первых пяти колонок

sort– сортировка строк. Полезные опции: -n - числовая сортировка, т.е. 2 идёт раньше чем 11; -kN - сортировка по колонке номер N. Колонки разделяются произвольным числом пробелов и табуляций. Пример:

ls -l | sort -n -k5 #Сортировка списка файлов по размеру (пятая колонка)

uniq – обработка повторяющихся строк. Умеет отбрасывать повторяющиеся строки и подсчитывать число повторов. Удобно применять вместе с sort. uniq может сравнивать строки целиком или начиная с некоторой позиции до конца строки.

grep – поиск строк по образцу. По умолчанию образец интерпретируется как регулярное выражение. Название программы происходит от команды редактора ed "g/re/p" - перейти к строке, содержащей регулярное выражение re и напечатать эту строку. Если нужно искать символы, имеющие особый смысл в регулярном выражении, то их нужно экранировать через слэш. Пример:

echo abc$ | grep c\\$  #Правильно
echo abc$ | grep 'c\$' #Правильно
echo abc$ | grep c$    #Строка не найдена

join – слияние файлов по ключевому полю. Файлы должны быть предварительно отсортированы. Пример слияния файлов file1 и file2, причем в первом файле ключ находится во второй колонке, а в о втором - ключ в третьей колонке:

join -1 2 -2 3 <(sort -k2 file1) <(sort -k3 file2)

find + xargs

Поиск файлов find

find [from_dir] [tests operators actions]

Команда find рекурсивно проверяет файлы и каталоги начиная с каталога from_dir на соответствие условиям tests, если какое-то условие не выполнено, то дальнейшие не проверяются и начинается проверка следующего файла/каталога. Условия могут объединяться логическими операторами, а при выполнении условий могут выполняться действия - actions.

Некоторые условия:

  • -name 'pattern' - поиск имени по шаблону в стиле _sh. В отличии от sh по '*' ищутся файлы, начинающиеся с точки, а '/' не срабатывает, поскольку проверяются имена внутри одного каталога
  • -regex pattern - поиск имени по регулярному выражению. Проверяется полное имя от стартового каталога.
  • -type [f|d|l..] - поиск файлов, каталогов, символических ссылок и т.п.
  • -mtime [+|-]n - поиск файлов по времени модификации в днях . '+' - старше чем n дней, '-' - младше чем n дней, без знака - в точности n дней назад
  • -mmin [+|-]n - то же, что и -mtime, но время в минутах
  • -size [+|-]n[kMG] - поиск файлов размером больше/меньше/равно n кило/Мега/Гига байт
  • -user name - поиск файлов пользователя

Действия:

  • -quit - немедленное завершение поиска
  • -delete
  • -print - печать имени начиная со стартового каталога. Рекомендуется добавлять в конец поиска если нужно просмотреть список найденных файлов
  • -print0 - то же, что и -print, но в качестве разделителя имён используется символ '\0'. Рекомендуется использовать при обработке найденных командой xargs
  • -printf format - печать информации о файле по формату. Разделитель имён надо вставлять в формат. %f - базовое имя без каталога, %p - полное имя с каталогом, %h - имя каталога, %s - размер.
  • -exec cmd args... {} \;' - выполнение внешней команды _cmd с аргументами. Вместо '{}' - подставляется имя файла; '\;' - признак конца аргументов (экранирующий слеш съедается шеллом).

Операторы:

  • -a - AND применяется по умолчанию
  • -o - OR
  • \! - NOT
  • \(...\) - группировка условий

В \! и \(...\) экранирующие слеши будут убраны шеллом.

Примеры

Поиск файлов определённого пользователя изменившихся за последние между часом и 30 минутами ранее и печать имени и времени модификации:

find /tmp -user mike -mmin -60 -mmin +30 -printf '%p %t\n'

Поиск файлов, содержащих строку 'example':

find /tmp -type f -exec grep -q example {} \; -print

Рекурсивная смена прав доступа на файлы:

chmod -R a-x mydir/* # Неправильно. Отберёт право на доступ к каталогам
find mydir -type f -exec chmod a-x {} \; # Правильно

Параллельное кодирование видеофайлов в каталоге в 8 потоков:

find ./video -type f -name \*.avi -print0 \
    | xargs -0 -P 8 -n 1 -I {} ffmpeg  -i {} -c:v libx264 -c:a copy {}.mp4

Аргументы команды: опции, строки, файлы

При запуске программы в Unix указывается имя исполняемого файла и список параметров, разделённых пробелами. Дополнительно, может быть задано перенаправление стандартных файлов ввода/вывода.

В зависимости от программы, параметры могут интерпретироваться как опции, как строки или как имена файлов. Единого стандарта нет, но есть несколько популярных соглашений. Однобуквенные опции, как правило, начинаются со знака минус: -x или -x значение, опции с длинными именами - с двух минусов: --xxx-xxx или --xxx-xxx=значение. Программы, которые не работают с файлами, могут использовать опции без знака минус.

Для того, чтобы отличить имена файлов от опций, программы, принимающие в качестве аргументов имена файлов, могут дополнительно использовать следующие соглашения:

  • Параметр начинающийся со знака минус, интерпретируется как опция, даже если в текущем каталоге есть файл с таким именем;
  • Параметр состоящий из двух знаков минус интерпретируется как последняя опция за которой идут только имена файлов;
  • Параметр состоящий из одного минуса интерпретируется как файл стандартного ввода или вывода (в зависимости от смысла выполняемого действия).

Примеры:

cat file # Команда cat интерпретирует параметр как имя файла
echo file # Команда echo интерпретирует параметр как текст
cat -n file # Обе команды интерпретируют -n как опцию
echo -n file # правда, с разным значением
cat -- -n file # Команда cat интерпретирует "--" как конец опций
echo -- -n file # Команда echo не интерпретирует "--" как конец опций
cat - file # Команда cat интерпретирует "-" как чтение из стандартного ввода
echo - file # Команда echo не читает из файлов и не придает "-" особого значения

dd if=file of=/dev/null # Команда dd использует нестандартный формат опций
ps ax --forest # Команда ps все аргументы трактует как опции. Короткие опции используются без минуса
java -version # java использует длинные опции с одним минусом

Команда test и [[expr]]

В командном языке bash операторы if и while могут использовать в качестве условия код завершения произвольной программы. Код ответа 0 интерпретируется как "истина", любой другой - как "ложь". Вместо if можно использовать операторы условного выполнения cmd1 && cmd2 - выполнить cmd2 если cmd1 завершилась успешно и cmd1 || cmd2 - выполнить cmd2 если cmd1 завершилась неуспешно.

Пример:

if grep --silent aaa file; then echo file \"file\" contain \"aaa\"; fi
grep --silent aaa file && echo file \"file\" contain \"aaa\"
grep --silent aaa file || echo file \"file\" not contain \"aaa\"

Для того, чтобы в качестве условия можно было бы писать традиционные выражения, была придумана команда test. Команда получает операторы и операнды в виде отдельных аргументов командной строки, вычисляет логическое условие и возвращает 0, 1 или 2 (в случае синтаксической ошибки).

Пример:

test "abc" = "cde" || echo "abc" not equal "cde"

Для красоты записи программа test имеет ещё одно имя - [ и вспомогательный последний аргумент ] . Две строчки ниже эквивалентны:

if test 1 -gt 0; then echo 1 \> 0;fi
if [ 1 -gt 0 ]; then echo 1 \> 0;fi

Аргументы команды test подвергаются обычным подстановкам и разбиением на слова, что часто приводит к ошибкам:

[ "A" > "B" ]       # неправильно
[ "A" \> "B" ]      # правильно
[ $A = HELLO ]      # ошибка если переменная A не определена, содержит пробелы или символы подстановки
[ "$A" = HELLO ]    # ошибка если $A начинается с минуса. Например -eq
[ x"$A" = xHELLO ]  # прием, позволяющий корректно провести сравнение

Для того, чтобы преодолеть указанные проблемы в язык введена синтаксическая конструкция [[expr]], которая разбирает выражение expr по тем же правилам, что и команда test, но при этом внутри скобок не производится подстановка имен файлов, перенаправление ввода/вывода и разбиение содержимого переменных на слова.

[[expr]] в отличие от [ expr ] не является независимой командой, что можно увидеть на примерах:

\[ -e file \]        # нормально
[ -e file ]          # то же самое
\[\[ -e file \]\]  # [[: command not found
[[ -e file ]]       # нормально

Набор операторов test и [[

Проверки объектов файловой системы: op path

  • -e объект существует
  • -f это файл
  • -s файл не нулевого размера
  • -d каталог
  • -b блочное устройство (например диск)
  • -c байтовое устройство (например модем)
  • -p именованный канал
  • -h -L символический линк
  • -S сокет

  • -r доступен на чтение

  • -w доступен на запись
  • -x доступен на выполнение

Проверка строк: op string

  • -z пустая строка
  • -n непустая строка

Сравнение строк: string1 op string2

  • = равны
  • != неравны
  • > больше
  • < меньше

Сравнение чисел: num1 op num2

  • -eq равны
  • -ne неравны
  • -gt больше
  • -lt меньше

Группировка: (expr)

Отрицание: ! expr

Логические операции в test: expr1 op expr2

  • -a И
  • -o ИЛИ

Логические операции в [[: expr1 op expr2

  • && И
  • || ИЛИ

Несовместимые реализации команд

Подстановка переменных в zsh

В bash постоянно приходится заботиться о переменных, содержащих пробелы (например A="$B"). Чтобы этого избежать, в zsh содержимое переменной подставляется как один аргумент и никак не интерпретируется. Следующие команды не сработают

A='*'; ls $A # Файл * не найден
A='ls -l'; $A # Команда "ls -l" не найдена 

Для совместимости с bash надо выполнить команды setopt GLOB_SUBST и setopt SH_WORD_SPLIT

base64

В Linux base64 file в MacOS base64 -i file. Команда base64 < file сработает и там и там.

Редактор Vim

Редактор vim (Vi IMprooved) является развитием vi (VIsual editor). В настоящее время в большинстве дистрибутивов под именем vi поставляется именно vim. В CentOS поставляются три пакета vim-minimal – vi, vim-enhanced – собственно vim и vim-common, набор макросов и вспомогательных программ. Благодаря набору макросов осуществляется подсветка синтаксиса для многих языков программирования, запуск программ на компиляцию, просмотр определения переменных и макросов и т.п.

Редактор имеет 5 режимов (modes):
«Нормальный»: текст не вводится, клавиши h,j,k,l (или стрелки) перемещают курсор, все остальные клавиши и их последовательности выполняют различные команды;
«Вставки/замены»: обычное экранное редактирование. Стрелки могут или не работать в зависимости от программы удаленного доступа;
«Визуальный» или «Выделения»: режим выделения текста с помощью клавиш перемещения курсора или специальных меток;
«Повтора»: после ввода числа в нормальном режиме следующая команда выполнится соответствующее количество раз. Например 5dd пять раз выполнит команду удаления строки;
«Командный»: для ввода команд, для которых не назначены управляющие клавиши.

Клавиша <Esc> (иногда – два нажатия) возвращает из любого режима в «нормальный».
i, a, R, o, O – переводит из «нормального» режима в режим «вставки».
Двоеточие из «нормального» режима переводит в «командный» режим.
Число переводит из «нормального» режима переводят в режим «повтора».
Символы v, V и Ctrl v – переводят из «нормального» режима в «визуальный».

Команды vim для программиста

Включить выключить автовыравнивание строк:
:set autoindent (:set ai)
:set noautoindent (:set noai)

Включить выключить подсветку синтаксиса:
:syntax on
:syntax off

Установить язык программирования если vim не распознал его автоматически:
set syntax=sh

Запустить make в текущем каталоге:
:make [param]

Перед запуском make желательно установить автоматическое сохранения редактируемых файлов перед компиляцией:
:set autowrite on

После завершения компиляции:
:cl - список ошибок
:cc [num] - показать ошибку с номером num или текущую
:cn - следующая ошибка
:cp - предыдущая ошибка

В режиме редактирования:
[i – просмотреть определение (первое вхождение в тексте) переменной
[d – просмотреть определение макроса (в языке Си)
% – найти парную скобку

Ctl-n или Ctrl-p – автодополнение, подстановка слов из имеющейся программы (а в Си и из заголовочных файлов) по введенным первым буквам
Ctrl-X Ctrl-L- автодополнение строки

Простые команды Vi

А любом режиме Esc, чтобы вернуться в нормальный. На некоторых клавиатурах Esc срабатывает с задержкой, поэтому kexit вводить Esc Esc/

В нормальном режиме:
:help [command] - просмотреть подсказку по vim в целом или посвященную команде command.
:q - выйти если в файле не было изменений
:wq, :x - записать и выйти
:q! - выйти без сохранения

u – UNDO последнее действие
U – UNDO вся строка
Ctrl-R – REDO

Переход в режим выделения
v - режим выделения символов и строк
V - режим выделения строк
Ctrl v - режим выделения прямоугольного блока символов

В визуальном режиме можно выделить блок, а затем
d – удалить в буфер (del)
с – удалить в буфер и перейти в режим вставки (cut)
y – копировать в буфер без удаления (yank)

Удаление в буфер
x - один символ
dw - слово
dd - строка

Вставка из буфера

p – вставить (paste) перед курсором
P - p – вставить после курсора

Переход в режим редактирования
i - перейти в режим вставки с позиции курсора
a - перейти в режим вставки с позиции после курсора
o - добавить пустую строку ниже и перейти в режим вставки
O - добавить пустую строку выше и перейти в режим вставки
R - перейти в режим замены
rx - заменить текущий символ на x

Позиционироваться в файле
:nnn - перейти на строку с номером nnn. :0 – начало файла, :$ или G – конец файла
) или ( – следующее или предыдущее предложение
} или { – то же для параграфа
]] или [[ – то же для секции, функции
% – ответная скобка (matching)
`` – предыдущее местонахождение, с точностью до символа
'' (два апострофа) – то же, с точностью до строки

Метки, к которым всегда можно вернуться:
mx – пометить текущую позицию буквой “x” (буква, разумеется, любая)
`x – перейти к метке “x”
'x – перейти к строке с меткой “x”

Поиск/замена:
/text – искать “text” ниже текущей позиции
?text – то же, но выше
n – повторить поиск в том же направлении
N – то же, но в обратном направлении
* – найти и пометить слово такое же, как под курсором ниже по файлу
# – то же, но выше по файлу

:[address]s/text/replacement/[gci] – в строках заданных address заменить “text” на “replacement”. Опции: g (Global)-все, c (Confirm) – с запросом, i (case Insensitive) -игнорируя регистр

Редакторы Ed и Sed

Редактор ed - очень простой интерактивный текстовый редактор, включенный в спецификацию стандарта POSIX. Этот редактор должен присутствовать в любой Unix подобной ОС, в том числе Linux. Фактически это так и есть, но некоторые реализациях могут отклоняться от стандарта. Например, busybox в эмуляторе Unix'а MobaXterm выдает приглашение на ввод команд и лишён поддержки регулярных выражений.

Набор команд ed используется в потоковом редакторе sed, а так же в популярном редакторе vim (там они доступны после ввода управляющего символа ':' ).

Редактор ed не имеет пользовательского интерфейса и не выводит на экран текст редактируемого файла. Это позволяет работать с редактором ed на очень медленных линиях связи и при плохом отклике системы (например при чрезмерной нагрузке).

При старте редактор ed считывает редактируемый файл в буфер в оперативной памяти и выполняет все операции с этим буфером. Буфер сохраняется в файл только после явного вызова команды записи. Такой способ редактирования отличает редактор ed от потокового редактора sed и не позволяет работать в ed с большими файлами.

Запуск редактора

ed [file]

Если указано имя файла, то при старте выдаётся число прочитанных байт. В классической реализации приглашение на ввод не выдается, а вывод числа байтов можно подавить опцией '-'. В MobaXterm выдается приглашение ':', а любые опции игнорируются.

Команды sed

Запуск

sed -i.bak -n -e 'cmd' -f cmdfile file1 file2...

По умолчанию, результат обработки выдаётся на стандартный вывод.

  • -i[ext] - редактирование файлов "на месте". Каждый файл обрабатывается отдельно. Результат сохраняется в тот же файл. Старое содержимое сохраняется в файле, к имени которого приписана строка ext.
  • -n - отмена автопечати обработанных строк. Для вывода строк необходимо явно указывать в скрипте команду p или аналогичную.
  • -e cmd - задание скрипта cmd в командной строке
  • -s cmdfile - чтение скрипта из файла cmdfile
  • file1 file2... - список входных файлов. При его отсутствии обрабатывается стандартный ввод.

Формат команд

[addr1 [,addr2]] C [options]

Адреса определяют строки, к которым должна быть применена команда. Если адрес не указан, то команда применяется ко всем строкам. Если указаны два адреса, то команда применяется ко всем строкам от addr1 до addr2 включительно. Адреса могут быть номерами строк (в том числе символ $ в качестве номера последней строки), регулярными выражениями в формате /re/ или \%re% (в этом случае % может быть заменён на любой символ). Запись addr! означает, что команду надо применять ко всем адресам, кроме указанного.

Команда кодируется одним символом. Опции зависят от типа выполняемой команды. Чтобы применить к одному адресу несколько команд, они могут быть сгруппированы с помощью фигурных скобок.

В файле отдельные команды могут располагаться в отдельных строках. При запуске однострочных программ команды отделяются точкой с запятой или передаются в виде последовательности опций -e 'cmd'

sed '1d;3d;s/abc/cde/'
sed -e '1d' -e '3,5d' -e '/start/{n;n;s/abc/cde/}'

Основной цикл

Редактор sed оперирует тремя объектами: входной поток строк, буфер строк (pattern space), буфер хранения (hold space), выходной поток. ( pattern space также переводят как "пространство регулярных выражений")

В цикле производятся следующие действия:

  • строка из входного потока читается в буфер строк. Из строки удаляется символ перевода строки;
  • к буферу строк последовательно применяются все команды с подходящими адресами (в том числе команды обмена между буфером строк и буфером хранения);
  • если не отключена автопечать, то содержимое буфера строк выводится в выходной поток. Туда же дописывается перевод строки;
  • буфер строк очищается и цикл повторяется.

Команды управления главным циклом

q # если не отключена автопечать, то вытолкнуть буфер строк в выходной поток,
  # завершить главный цикл
n # если не отключена автопечать, то вытолкнуть буфер строк в выходной поток,
  # загрузить из входного потока в буфер строк следующую строку,
  # продолжить выполнять команды уже с новым содержимым

Команды изменения строк

s/from\(.*\)/to\1/gi # замена регулярного выражения в буфере строк
y/abc/cde/ # Замена парных символов в буфере строк. Аналог команды tr.

Вставка/замена/удаление строк

text - последовательность строк, разделяемых комбинацией символов \<перевод строки>.

i  text # вывести в выходной поток указанный текст
a  text # вытолкнуть буфер строк в выходной поток,
        # затем вывести в выходной поток указанный текст
c  text # замена строк. Удалить строки в диапазоне из входного потока,
        # затем вывести в выходной поток указанный текст
d # очистить буфер строк и перейти на начало главного цикла
D # удалить первую строку в буфер строк
  # и перейти на начало главного цикла без считывания новой строки

Команды управления буферами

N # добавить в буфер строк перевод строки и следующую строку из входного потока
g # скопировать буфер хранения в буфер строк
G # добавить в буфер строк перевод строки и содержимое буфера хранения
h # скопировать буфер строк в буфер хранения 
H # добавить в буфер хранения перевод строки и содержимое буфера строк
x # поменять местами буфер строк и буфер хранения 

Если буфер хранения пуст, то команда G добавляет в буфер строк только перевод строки.

Печать

Опция -n отключает автоматический вывод результата в выходной поток. В этом случае команды печати надо указывать явно.

p # скопировать (не очищая) буфер строк в выходной поток
P # скопировать первую строку буфера строк в выходной поток
l # скопировать  буфер строк в выходной поток,
  # предварительно пометив конец строки знаком $,
  # и заменив непечатаемые символы их кодами в стиле языка Си
= # вывести номер текущей строки + перевод строки в выходной поток

Команды работы с файлами

r filename # вывести содержимое файла в выходной поток перед началом следующего цикла.
w filename # записать буфер строк в конец файла. При запуске скрипта файл обнуляется.

Метки и ветвления

: LABEL # метка
b [LABEL] # безусловный переход на метку, а при ее отсутствии на начало главного цикла
t [LABEL] # переход на метку в случае успешного выполнения хотя бы одной команды 's'.
        # При отсутствии метки переход на начало главного цикла

Команды редактора ed

Структура команд

Большинство команд ed имеют вид:

[addr]C[args]

Где addr - адреса строк, к которым надо применить команду, C - односимвольная команда, args - дополнительные аргументы команды. Адрес addr может отсутствовать, указывать на одну строку или на диапазон строк. По умолчанию, команды редактирования применяется к текущей строке, а файловые команды ко всему буферу.

Адреса

Адреса задаются следующими способами:

По номерам (n обозначает число), как результат поиска регулярного выражения, как смещение относительно известного адреса или как диапазон от адреса до адреса:

  • n - номер строки. 0 означает строку перед первой;
  • $ - последняя строка в буфере;
  • . - текущая строка. На старте устанавливается в $;
  • /RE/ - первая строка соответствующая регулярному выражению RE. Поиск идёт вниз по тексту Если RE не найдено до конца, то поиск продолжается по кругу с начала. В sed - все строки соответствующие выражению RE.
  • ?RE? - то же, что и /RE/. но поиск идёт вверх по тексту . Не актуально для sed.
  • addr+n или addr-n - смещение относительно адреса, например, /RE/+2 или $-3 (четвертая строка с конца);
  • addr1,addr2 - диапазон от и до включительно;
  • [addr1,addr2]g/RE/ - все строки в диапазоне addr1-addr2, соответствующие регулярному выражению RE;
  • [addr1,addr2]v/RE/ - все строки в диапазоне addr1-addr2, не соответствующие регулярному выражению RE;
  • 'C - строка, помеченная символом C. Метка устанавливается командой [addr]kC.

Диапазон может указываться через точку с запятой. В этом случае если адрес addr2 задан в виде поиска регулярного выражения, то при использовании запятой поиск ведётся от строки, следующей за текущей строкой, а при использовании точки с запятой - от строки, следующей за адресом addr1.

Команды

Общие

  • q - завершить работу
  • Q - забыть изменения и завершить работу
  • u - отменить изменения, сделанные последней командой редактирования
  • f file - задать текущее имя файла. Удобно если ed запускался без указания имени файла.
  • [addr]r file - вставить содержимое файла после адреса. По умолчанию в конец буфера. r !cmd - выполнить шелловскую команду и вставить её вывод
  • e file - удалить содержимое буфера и начать редактировать новый файл. e !cmd - аналогично r !cmd
  • [addr1,addr2]w[ file] - записать буфер в файл (можно указать новое имя)

Ввод строк

  • [addr]a - вставить строки после указанной
  • [addr]i - вставить строки перед указанной
  • [addr1,addr2]с - удалить строки из диапазона и вставить вместо них новые

В командах вставки признаком конца ввода является строка состоящая из одного символа точки и перевода строки. Для ввода одной точки в строке вводятся две точки.

Печать строк

  • [addr1,addr2]p - напечатать строки из диапазона
  • [addr1,addr2]n - напечатать строки из диапазона, вставив перед каждой её номер и символ табуляции.

Удаление и копирование

  • [addr1,addr2]d - удалить строки
  • [addr1,addr2]m[addr] - переместить строки в позицию после адреса addr. Если addr==0, то в начало буфера.
  • [addr1,addr2]m[addr] - скопировать строки в позицию после адреса addr.

Контекстная замена

  • s/SRC/DST/opt произвести контекстную замену в строке. Opt: g - все вхождения в строке, i - игнорировать регистр.

Регулярные выражения

  • Для группировки используются скобки \( и \)
  • Найденные группы обозначаются \1, \2...
  • ^, ., $ - начало строки, произвольный символ, конец строки
  • * - повторитель предыдущего символа или группы от 0 до бесконечности
  • {m,n} - повторитель от m до n. {m} означает ровно m вхождений; {m,} - по крайней мере m вхождений; {m,n} - любое число вхождений от m до n включительно

Синтаксис bash

Краткий свод управляющих конструкций языка программирования bash.

Во всех управляющих конструкциях в качестве логического значения используется код возврата из программы, указанной в качестве условия. Код возврата 0 – истина, любое другое значение – ложь. Программа true – всегда завершается с кодом 0, false – всегда завершается с кодом 1. Команда test (она же [...] ) вычисляет код ответа на основе выражения, переданного через параметры командной строки.

Конструкции могут быть записаны в несколько строк, или в одну с использованием разделителя ";".

Последовательности команд. Возвращают код ответа последней выполненной команды.
; - оператор безусловного последовательного выполнения команд
&& оператор И. Правая часть не выполняется если левая выполнилась неуспешно.
|| оператор ИЛИ. Правая часть не выполняется если левая выполнилась успешно.

Оператор if – условное выполнение.
if cmd
then
command...
else
command...
fi

Запись в одну строку
if cmd ; then command1;command2…;else command3;command4…;fi

Цикл while выполняется, пока команда условие возвращает 0
while condition-is-true
do
command...
done
Запись в одну строку
while cmd; do command1; command2;done

Пример с использованием встроенной функцией test
VAR0=0; LIMIT=10
while [ "${VAR0}" -lt "${LIMIT}" ];do
echo -n "${VAR0} " # -n подавляет перевод строки
VAR0=`expr ${VAR0} + 1`
done

Пример в сочетании c арифметической подстановкой
a=1
while (( a <= LIMIT )) ; do # В (()) $ не нужен
echo -n "$a "
((a += 1)) # В арифметической подстановке есть оператор +=
done

Пример с командой read, которая read читает строки из стандартного ввода. read разбивает строку на слова и сохраняет их в указанных переменных. Если переменные не заданы, то read сохраняет всю строку в переменной REPLY. Если необходимо читать посимвольно, то команде read можно указать опцию -n 1
while read; do
echo $REPLY
done < file.txt

Цикл until аналогичен while, но выполняется пока команда завершается с ненулевым кодом возврата
until condition-is-true; do
command...
done

Цикл for выполняется путем последовательной подстановки в переменную цикла значений из списка
for ARG in LIST; do
command...
done

Простая форма
for ARG in "$VAR1" "$VAR2" "$VAR3" ; do
echo $ARG
done

В сочетании с подстановкой имен файлов по шаблону
for FILE in [ab]*; do
echo "$FILE" # В отличие от echo [ab]*, имена печатаются в отдельных строках
done

В сочетании с арифметической подстановкой
LIMIT=5
for ((a=1; a <= LIMIT ; a++)); do # $ не нужен ни перед скобками ни перед именами переменных
echo -n "$a "
done

В сочетании с программой seq
LIMIT=5
for ARG in `seq 1 $LIMIT`;do
echo -n "$ARG "
done

Оператор case выбор одного из вариантов в соответствии со значением аргумента
case "$VARiable" in
"$condition1" )
command...
;;
"$condition2" )
command...
;;
esac

Переменные в bash

Переменная в языке shell - это макрос, который может быть подставлен в строку команды перед её разбором. Оператор ${VAR} заменяется текстовой строкой, хранящейся в переменной с именем VAR. После подстановки значение переменной будет разбито на отдельные слова по пробельным символам. Если содержимое переменной должно интерпретироваться как одно слово, то оператор подстановки надо взять в кавычки "${VAR}"

Интерпретатор `bash` использует как минимум три типа переменных, отличающихся областью видимости:

A=BCD # Локальная переменная, доступная из данного скрипта
A=BCD cmd # Именованный параметр, передаваемый в окружение программы cmd не влияющий на текущий скрипт
export A=BCD # Глобальная переменная, видимая в текущем скрипте и в запускаемых программах

Переменные в bash не имеют типа. Можно считать, что переменная всегда содержит текстовую строку. Если требуется интерпретация переменной как числа, то проводится разбор строки слева. Значение определяют цифры до первого нечислового символа. Строка не содержащая цифр интерпретируется как 0.

set – выдает список всех переменных с их значениями

VAR="string" - определяет локальную переменную интерпретатора и присваивает ей значение. Разделителями в команде являются символ = после имени переменной и первый пробел после значения. Пробелы вокруг знака равенства недопустимы. Пробел слева от знака равенства интерпретируется как часть имени, пробел справа – как пустая присваеваемая строка. Если строка содержит пробелы, то она должна быть заключена в кавычки.
$VAR – подстановка значения переменной VAR. При разборе строки именем переменной считается максимальная последовательность из букв, цифр и знаков подчеркивания.
${VAR} - то же что и $VAR позволяет избавиться от неоднозначности при разборе строки

export VAR делает переменную доступной для дочерних процессов (делает переменную глобальной)
export VAR=string допустимое объявление глобальной переменной
unset VAR уничтожает определение переменной

Пример экспорта переменной:
WORKDIR=/usr/src/linux
echo $WORKDIR #используем значение переменной
bash #запустили новую копию интерпретатора
echo $WORKDIR #переменная недоступна
exit # завершили копию интерпретатора
echo $WORKDIR #переменная снова доступна
export WORKDIR
bash
echo $WORKDIR #после экспорта переменная доступна запускаемым программам

Дополнительные возможности при работе с переменными

${VAR-default} - если VAR определена, то ее значение иначе значение default
${VAR=default} - если VAR определена, то ее значение иначе значение default и присваивание его VAR
${VAR?err_msg} - если VAR определена, то ее значение иначе печать err_msg
Пример подстановки вывода команды whoami в качестве значения по умолчанию:
echo ${username-`whoami`}

${#VAR} - длина значения переменной в символах
${#array[*]} или ${#array[@]} - размер массива (Массивы доступны в версии bash > 2)
${#*} или ${#@} число параметров скрипта

${VAR:pos} - подстрока с позиции pos
${VAR:pos:len} - подстрока с позиции pos длинной length

В следующих операциях Pattern это выражение в формате glob - * - любая последовательность символов, ? - один символ.

${VAR/Pattern/Replacement} - замена первого вхождения Pattern на Replacement, если Replacement отсутствует, то Pattern удаляется
${VAR//Pattern/Replacement} - глобальная замена
$(VAR#Pattern} - удаление минимальной строки, соответствующей Pattern в начале строки (удаление префикса)
$(VAR##Pattern} - удаление максимальной строки, соответствующей Pattern в начале строки
$(VAR%Pattern} - удаление минимальной строки, соответствующей Pattern в конце строки (удаление суффикса)
$(VAR%%Pattern} - удаление максимальной строки, соответствующей Pattern в конце строки

Пример:

VAR="file.test.txt"
echo ${VAR#file*.} => test.txt
echo ${VAR##file*.} => txt
echo ${VAR%.*} => file.test
echo ${VAR%%.*} => file

Спецсимволы в bash

Далее перечислены символы и синтаксические конструкции, имеющее особое значение в bash. Для ввода спецсимволов как они есть используют кавычки или спецсимвол \ отменяющий специальное значение следующего символа

\ Экранирование. Отменяет специальное значение следующего символа
\\ Символ "\"

# Комментарий, не работает в кавычках и в некоторых подстановках переменных и преобразовании основания чисел
echo "Это #не комментарий"
echo 'Это # не комментарий’
echo Это \# не комментарий
echo Это # Вот комментарий.
echo ${PATH#*:} #Специальная переменная
echo $(( 2#101011 )) #Преобразование системы счисления в арифметической подстановке.

>, >> - перенаправление стандартного вывода программы в файл
< - перенаправление стандартного ввода программы из файла
<<TERM перенаправление стандартного ввода программы из текста текущего скрипта со следующей строки до строки, состоящей из слова TERM.
|- перенаправление стандартного вывода программы на стандартный ввод другой программы

; Разделитель команд в строке
echo hello; echo world

;; Разделитель альтернатив в операторе case
case "$VARiable" in
abc) echo "$VARiable = abc" ;;
xyz) echo "$VARiable = xyz" ;;
esac

. Аналог команды source (#include в С++). Выполняет скрипт в текущем интерпретаторе.
. myconf

".." Двойные кавычки, отменяют действие спецсимволов кроме $ `..` и \

'...' Апострофы, отменяют действие всех спецсимволов в том числе и \, по этому нельзя включить апостроф в строку ограниченную апострофами

: Нулевая команда, всегда возвращает нулевой код ответа. В сочетании с перенаправлением ">" создает файл, или обнуляет существующий. В сочетании с перенаправлением ">>" создает файл, или изменяет время модификации существующего
:> data.xxx # File “data.xxx” now empty.
(можно и без двоеточия)

Шаблоны в именах файлов. Если подходящие имена находятся, то они подставляются в командную строку как отдельные аргументы (возможно с пробелами внутри). Если имена не находятся, то шаблон остается как есть.

* Шаблон заменяющий любую последовательность символов
? Шаблон заменяющий ровно один символ
[xyz] Шаблон заменяющий один из перечисленных символов
{xxx,yyy,zzz,...} Подстановка одного из вариантов в шаблон. В скобках не должно быть неэкранированных пробелов
grep Linux file*.{txt,htm*} # Ищет слово “Linux” в файлах вида “fileA.txt”, “file2.txt”, “fileR.html”, “file-87.htm”, etc.

$ Подстановка значения переменной, арифметического выражения или стандартного вывода программы. Если значение содержит пробелы, то при подстановке оно разбивается на отдельные аргументы.
$A содержимое переменной A
$$ PID процесса
$? Код возврата из последней выполненной программы или функции, а также код возврата самого скрипта
$((2*2)) подстановка результата вычисления арифметического выражения
$(cmd) подстановка стандартного вывода программы
`...` тоже, что и $(...) – подстановка стандартного вывода программы

Пример: A=EE; echo $A $(echo QQ) $((7+5))
Результат: EE QQ 12
Ошибка: $A=ZZ
Результат: bash: EE=ZZ: command not found

(...) Группировка команд
(A=hello; echo $A)
Для выполнения группы в скобках запускается новый интерпретатор
A=123
(A=321)
echo A = $A # A = 123
# "A" внутри скобок – локальная переменная.

(...) Создание массива ( только в bash версии > 2)
Array=(element1 element2 element3)

[] Элемент массива ( только в bash версии > 2)
Array[1]=slot_1
echo ${Array[1]}

{1..10} - подстановка чисел от 1 до 10
{c..n} - подстановка символов от "c" до "n"

{...} Создание безымянной функции, удобно для перенаправления ввода/вывода нескольких команд в один файл. В отличие от настоящей функции видимости переменных не изменяется.
PACK=mysql
{
echo
echo "Archive Listing:"
rpm -qpl ${PACK} # Список фалов в пакете rpm
echo
rpm -i --test ${PACK} # Проверка, установлен ли пакет.
} > "${PACK}.txt" #И весь вывод в один файл.

[...] Встроенная функция test для вычисления логических выражений

((...)) Арифметическая подстановка, вычисляет арифметическое выражение в стиле языка Си внутри скобок

& - запуск программы в фоновом режиме
bash$ sleep 10 &
[1] 850
[1]+ Done sleep 10

Спецсимволы в командной строке

Каждая символ, введенный пользователем, обрабатывается драйвером терминала, а затем интерпретатором командной строки. В разных ОС набор спецсимволов может быть различным. Здесь описаны Linux и bash.

Управление процессами (обрабатываются драйвером терминала):

  • Ctrl D - символ конца файла при вводе с клавиатуры. Сообщает программе, что ввод закончился.
  • Ctrl C - отправка программе сигнала на завершение. Может быть проигнорировано.
  • Ctrl Z - перевод программы в фоновый режим без завершения. Работа с программой может быть продолжена после выполнения команды fg в bash.
  • Ctrl S/Ctrl Q - остановка/продолжение вывода программы на экран. Дублируется клавишей ScrollLock.

Горячие клавиши bash:

  • Ctrl A – курсор в начало строки.
  • Ctrl E – курсор в конец строки.
  • Alt F/Alt B - перемещение на слово вперёд/назад.
  • Ctrl P, Ctrl N (Стрелки вверх/вниз) – просмотр истории команд.
  • Ctrl R – поиск в истории команд, вводимые символы интерпретируются как уже выполнявшаяся команда. По мере нахождения соответствий делается подстановка. Повторное нажатие Ctrl R ищет предыдущее вхождение строки в истории команд. При нахождении нужного варианта можно нажать Enter для выполнения или Ctrl E для выхода из режима поиска в режим редактирования.

TAB – автодополнение. Самая функциональная клавиша в bash. При вводе имени программы нажатие TAB приводит к поиску по первым введенным буквах всех программ в каталогах перечисленных в PATH. Если результат однозначный то производится подстановка, если нет, то повторное нажатие TAB приводит к выводу всех возможностей. При вводе параметров делается попытка завершить имя существующего файла по указанному пути (если в строке нет / то в текущем каталоге).

История команд:

  • !! -выполнение предыдущей команды.
  • sudo !! -выполнение предыдущей команды через sudo.

Сокращения имен каталогов:

  • ~ – домашний каталог пользователя
  • ~– - предыдущий посещённый каталог
  • ~+ – полное имя текущего каталога

Сокращение для предыдущего каталога позволяет удобно работать с двумя каталогами. Например

$cd ~/work
$cd /tmp
$cd ~-
$cd ~-
$echo ~+
/tmp

Инструментарий программиста в Linux: MAKE

make

Утилита make автоматически определяет, какие части программы должны быть перекомпилированы и вызывает команды для их перекомпиляции. Наиболее часто make используется для компиляции C-программ и содержит особенности, ориентированные именно на такие задачи, но можно использовать make с любым языком программирования. Более того, применение утилиты make не ограничивается программами. Можно использовать еe для автоматизации любой задачи, где некоторые файлы должны автоматически порождаться из других.

Makefile

Прежде чем использовать make, необходимо создать файл, называемый make-файлом, который описывает отношения зависимости между исходными и результирующими файлами и содержит команды для пересборки результирующих файлов. В C++ исполняемый файл зависит от объектных файлов, которые, в свою очередь, зависят от исходных файлов и файлов заголовков.

Для make-файлов зарезервированы имена GNUmakefile, makefile и Makefile, причем поиск идет в указанном порядке. Если необходимо использовать нестандартное имя, то его можно передать явно через опцию -f.

Когда make-файл уже написан, для сборки проекта достаточно выполнить в каталоге, где он находится, команду make.

Простой make-файл состоит из правил (инструкций) следующего вида:

ПЕРЕМЕННАЯ = ЗНАЧЕНИЕ

ЦЕЛЬ1 ... : [ЗАВИСИМОСТЬ ...]
    КОМАНДА 1  
    КОМАНДА 2
ЦЕЛЬ2 ... : [ЗАВИСИМОСТЬ ...]
    КОМАНДА 1
    КОМАНДА 2  
...
  • ПЕРЕМЕННАЯ - похожа на переменную в sh. Может использоваться для подстановки значения в целях, зависимостях и командах
  • ЦЕЛЬ - обычно имя файла, который надо создать. Примерами целей являются исполняемые или объектные файлы. Цель также может быть именем выполняемого действия, как, например, clean.
  • ЗАВИСИМОСТЬ - это файл, изменение которого требует персборки цели. Часто цель зависит от нескольких файлов.
  • КОМАНДА - это действие, которое выполняет make, например запуск компилятора или удаление временных файлов. Каждая строка правила начинается с символа табуляции. Правило может иметь более чем одну команду - каждую на своей собственной строке. Длинные строки разбиваются на несколько с использованием обратного слэша, за которым следует перевод строки. Знак диез # является началом комментария. Строка с # до конца игнорируется. Комментарии так же могут переноситься на несколько строк с помощью обратного слэша в конце строки.

Запуск make

Синтаксис:

make [Опции] [Переменная='abc'] [Цель]

Квадратные скобки означают необязательность присутствия данной части.

  • Цель - имя цели, которую надо выполнить. По умолчанию - первая цель, описанная в make-файле.
  • Переменная ='abc' - переопределение переменных. Значения переменных, введенных в командной строке, имеют больший приоритет, чем определения в make-файле.

Опции:

  • -f file - явное задание имени make-файла
  • -n - имитация действий без реального выполнения, служит для отладки
  • -t - изменение времени модификации цели без реального выполнения
  • -q - проверка на необходимость обновления цели без реального выполнения.

Более сложные способы применения MAKE

Для автоматической генерации зависимостей от файлов заголовков в языках C и C++ можно использовать команду gcc -M file.c или gcc -MM file.c. Второй вариант отличается тем, что не генерирует зависимости от системных заголовочных файлов.

Правила написания Makefile

  • В качестве ЦЕЛИ или ЗАВИСИМОСТИ может использоваться список файлов через пробел или шаблон в стиле shell.
  • Команды в правилах начинаются со знака табуляции.
  • Порядок правил кроме первого несущественен.
  • По умолчанию главной целью make является первая цель первого правила в первом make-файле. Цель можно явно задать при запуске make.
  • Цель, начинающаяся с точки, не используется как цель по умолчанию, если она не содержит  один или более символов / т.е. определяет путь к файлу; кроме того, по умолчанию не используются цели, определяющие шаблонные правила.
  • Шаблоны интерпретируются в момент выполнения правила, при присваивании переменным интерпретация шаблона не происходит.

Автоматические переменные

В КОМАНДАХ можно использовать автоматические переменные. Эти переменные заново вычисляются для каждого выполняемого правила на основе цели и зависимостей правила.

Автоматическая переменная Назначение
$@ Имя файла цели правила. В шаблонном правиле с несколькими целями,имя той цели, которая вызвала выполнение команд правила.
$< Имя первой зависимости. Если цель получила свои команды из неявного правила, то это будет первая зависимость, добавленная неявным правилом.
$? Имена всех зависимостей, которые являются более новыми, чем цель, с  пробелами между ними.
$^ Имена всех зависимостей, с пробелами между ними. Если Вы для цели неоднократно укажете одну и ту же зависимость, значение переменной '$^' будет содержать только одну копию ее имени.
$+ Эта переменная аналогична переменной '$^', только зависимости, указанные неоднократно дублируются в том порядке, в котором они указаны в make-файле. Это в первую очередь полезно для использования в командах компоновки, где является существенным повторение имен библиотек в определенном порядке
$* База с которой сопоставляется неявное правило (см. ниже). В шаблонном правиле база представляет собой часть имени файла, которая сопоставляется символу '%' в шаблоне цели. Если целью является файл 'dir/a.foo.b', а   шаблон цели - 'a.%.b', то базой будет 'dir/foo'. База полезна для создания имен файлов, связанных с правилом. В явных правилах база не определена как имя файла без расширения,если такое расширение можно выделить. Не рекомендуется использовать эту переменную в явных правилах

Неявные правила

Неявные правила определены для многих языков программирования и применяются в соответствии с расширением исходного файла. По умолчанию в gnu make список расширений такой : .out, .a, .ln, .o, .c, .cc, .C, cpp, .p, .f, .F, .r, .y, .l, .s, .S, .mod, .sym, .def, .h, .info, .dvi, .tex, .texinfo, .texi, .txinfo, .w, .ch, .web, .sh, .elc, .el. При использовании неявных правил используются переменные, переопределяя которые можно управлять процессом преобразования файлов, например, указывать нестандартный компилятор или передавать ему опции.

Исходный файл Порожденный файл Команда
Компиляция C-программ 'file.c' 'file.o' $(CC) -c $(CPPFLAGS) $(CFLAGS) file.c
Компиляция программ на языке C++
'file.cc'
или 'file.C'
'file.o' $(CXX) -c $(CPPFLAGS) $(CXXFLAGS) file .cc
Компиляция программ на Фортране
'file.f'
'file.o' $(FC) -c $(FFLAGS) file .f

Пример MakeFile/Использование действий по умолчанию

# Цель по умолчанию  - исполняемый edit
edit : main.o kbd.o command.o display.o
    cc -o edit main.o kbd.o command.o display.o

main.o : main.c defs.h
    cc -c main.c
kbd.o : kbd.c defs.h command.h
    cc -c kbd.c
command.o : command.c defs.h command.h
    cc -c command.c
display.o : display.c defs.h buffer.h
     cc -c display.c
clean :
    rm edit main.o kbd.o command.o display.o

По умолчанию, make начинает с первой цели (не считая целей начинающихся с точки). Это цель по умолчанию. В нашем случае это цель edit. Если файл edit новее чем файлы, от которых он зависит, то ничего не произойдет. Зависимости вычисляются рекурсивно для всех файлов, от которых зависит edit. Перекомпиляция и сборка должна быть проведена, если исходный файл или любой из заголовочных файлов, упомянутых среди зависимостей, обновлен позднее, чем объектный файл, или если объектный файл не существует.

Правилу clean не соответствует никакого создаваемого файла и, соответственно, clean ни от чего не зависит и само не входит в список зависимостей. При запуске по умолчанию clean вызываться не будет. Для его выполнения необходимо явно указать цель при запуске make: make clean

Для сокращения записи можно использовать переменные и действия по умолчанию (неявные правила)

.PHONY : all clean 

all: edit
objects = main.o kbd.o command.o display.o

edit : $(objects)
    cc -o edit $(objects)
main.o : defs.h
kbd.o : defs.h command.h
command.o : defs.h command.h
display.o : defs.h buffer.h
clean :
    rm edit $(objects)

Переменная objects позволила использовать единожды написанный список объектных файлов, а для объектных файлов в make встроено неявное правило по умолчанию

file.c: file.o   $(CC) -c file.c

Специальная цель .PHONY является встроенной в make и определяет свои зависимости как цели-имена, которым нет соответствия в виде файлов. Если данное правило пропустить, то создание в текущем каталоге файла с именем clean заблокирует выполнение make clean. Использование правил по умолчанию позволяет изменить стиль записей зависимостей:

objects = main.o kbd.o command.o display.o

edit : $(objects)
       cc -o edit $(objects)

$(objects) : defs.h
kbd.o command.o : command.h
display.o : buffer.h

Данная запись указывает, что все объектные файлы зависят от заголовочного файла defs.h, но для некоторых из них проверяются дополнительные зависимости.

Контрольные вопросы

Список вопросов

+++++++++++++
Программа man форматирует и выдает в интерактивном режиме справочную информацию, например man cat выдает опции команды cat.
На сочетания клавиш ^C она не реагирует, ^D интерпретирует как PgDown. Как из неё выйти, не зная команды на выход?
+++++++++++++
Предположим, что в файле /etc/passwd есть запись
user123:x:10123:500:special user:/:/usr/bin/bc
Что сможет сделать пользователь user123, получив доступ через терминал?
+++++++++++++
Напишите команды, выполняющие следующие действия:

Выдать на экран слово «file»

Выдать на экран содержимое файла с именем «file»

Одной командой выдать на экран содержимое нескольких файлов «file1» «file2» «file3»

Одной командой выдать на экран содержимое всех файлов в каталоге /tmp имена которых начинаются с «file1»

Выбрать из вывода предыдущей команды все строки содержащие слово «make» и показать на экране последние четыре строки из отобранных
+++++++++++++++++++++++++++++
Как создать файл с именем «???»

Как удалить все файлы, имя которых имеет длину 3 символа и начинается с вопроса?

Как удалить в текущем каталоге все файлы и подкаталоги, имя которых начинается с точки?

Как удалить в текущем каталоге ВСЕ файлы и подкаталоги?

++++++++++++++++++++++++++++
Что выведут команды echo?

A='*'
echo "$A"

echo '$A'

echo $A

+++++++++++++
Что произойдёт при выполнении двух команд?
echo=qqq
echo $echo

Что произойдёт при выполнении двух команд?
A=echo
$A $A > $A

Судя по всему, bash выполняет перенаправление файлов до подстановки переменных. Исходя из этого, попытайтесь представить, что произойдёт в третьей команде
A=echo
O=’>’
$A $A $O $A
+++++++++++++++++++++++++++++++
Что произойдёт при выполнении команды?
ed file.txt <<EOF
1,\$s/a/b/g
w
q
EOF

+++++++++++++
Чем отличаются две команды в редакторе vi?
:!q

:q!
++++++++++++++++++++++++++++++++++
Что изменится после выполнения команды?
export PATH=$PATH:~/bin
+++++++++++++
Что напечатают программы (запущенные от обычного пользователя)?
touch /tmp/$$; echo $?; rm /tmp/$$

touch /$$; echo $?; rm /$$
++++++++++++++++++++++++++++++++
Арифметическое выражение в двойных скобках без знака $, например ((A=A-3)) ничего не подставляет в командную строку, но возвращает код завершения. Код равен 0 если результат не 0, код равен 1 если вычислен 0 или произошла ошибка
Что напечатают команды?
((1+2)) || echo $?

((A=1+2)) && echo $? && echo $A

+++++++++++++
Файл /etc/passwd состоит из строк, разбитых двоеточиями на поля. Формат такой
Логин:Пароль:uid:gid:комментарий:домашний каталог: командная строка
Предположим у на с есть пользователь user. Что выдаст команда?

ls $(grep user /etc/passwd| cut –d: -f6)
+++++++++++++
Какой вариант записи оператора самый правильный (пометить галочкой):
if grep qq file then echo success fi
if grep qq file; then echo success; fi
if grep qq file; then; echo success; fi
+++++++++++++
В каталоге находятся файлы с именами a1, a2…a9, b1,b2…b9. Напишите три варианта цикла for который бы выполнял бы какую-нибудь операцию (например grep qq) со всеми файлами с b2 по b6. Один вариант должен использовать подстановку {}, другой [], третий (()).
+++++++++++++
Почему команда выдаст Not Null?
A=0
if [ $A > 0 ]; then echo Not Null;fi
+++++++++++++
Напишите скрипт, который проверял бы, что имя является файлом и печатал соответствующий текст (/etc/passwd – файл, /etc - не файл)
++++++++++++
У программы ps есть ключ u (user) который добавляет имя пользователя в первую колонку списка процессов. У команды сортировки sort есть ключ –u (uniq, уникальный), который говорит, что повторяющие строки после сортировки отбрасываются. Выдайте список всех пользователей, у которых сейчас есть запущенные процессы.
+++++++++++++
Команда wc (word count – подсчёт слов) имеет ключи –c –w –l, которые указывают что надо подсчитать число символов, слов или строк соответственно.
Напишите команду, которая подсчитает число процессов запущенных пользователем с именем student
+++++++++++++
Большинство стандартных каталогов в Unix имеют владельца root группу root доступа и права rwxr-xr-x Объясните, зачем обычным пользователям даны два права x и r
+++++++++++++
Используя команды: wc –l (выдает число строк в файле file в формате 526<пробел>file), cut (или awk), head, tail и цикл for напишите скрипт, который выводит задом наперед (вначале последняя строка, потом предпоследняя и т.д) содержимое файла, имя которого находится в переменной $1. (Примечание. В Unix есть стандартная команда tac, которая выполняет нужное преобразование, но её использование будем считать неспортивным)
+++++++++++++
В CentOS Linux в файле /etc/init.d/functions есть такие строки
MOVE_TO_COL="echo -en \\033[${RES_COL}G"
SETCOLOR_SUCCESS="echo -en \\033[1;32m"
SETCOLOR_NORMAL="echo -en \\033[0;39m"
Предположите, что произойдёт, если выполнить скрипт
. /etc/init.d/functions
RES_COL=40; $MOVE_TO_COL; $SETCOLOR_SUCCESS OK; $SETCOLOR_NORMAL; echo
Зачем нужна точка в первой строке этого скрипта?
+++++++++++++
Тестовая программа test.c
#include "test.h"
int main() { return 0; }

Что неверно в таком запуске компилятора
gcc test.c jpeg.h

Какой файл будет создан при таком запуске компилятора
gcc –с test.c

Какие файлы будут использованы для сборки программы test при таком запуске
gcc –o test test.o -ljpeg
+++++++++++++
Программа sendmail использует для доставки почты файлы /etc/mail/mailertable и /etc/mail/virtusertable. Для ускорения доступа эти файлы программой makemap компилируются в двоичный вид - mailertable.db и virtusertable.db.

makemap hash <текстовый_файл> <скомпилированный_файл>

Напишите такой Makefile, чтобы после изменения текстовой версии любого из указанных файлов достаточно было перейти в /etc/mail/ и набрать make, для обновления скомпилированной версии.
+++++++++++

Тестовые задачи

Задачи на этой странице имеют различный уровень сложности с точки зрения количества строк кода, которые надо написать, но они не требуют применения каких-либо сложных алгоритмов.

1 Языковая статистика1

Написать скрипт, который подсчитывает статистику длин слов в тексте. Выдача - таблица из двух колонок: длина слова, число слов с такой длиной, встретившихся в тексте. Границами слов считать любые не буквы.

2 Языковая статистика2

Взять любой литературный текст из интернета сохранить в однобайтовой кодировке (или перекодировать в такую кодировку командой iconv)

Написать скрипт, подсчитывающий статистику распределения по частоте русских букв (включая пробел). Выдача - таблица из двух колонок: буква, процент появлений данной буквы от общей длины текста.

3 Языковая статистика3

Найти в литературном произведении наиболее часто встречающееся слово из 5 букв

4 Определение кодировки

Написать программу автоматического определения однобайтовой кодировки русских литературных текстов (из набора KOI8, CP1251, CP866).

Для предварительной проверки того, что в файле просто текст можно использовать проверку на максимальную длину слова между пробельными символами (<25). Для проверки кодировки можно построить частотную статистику, а можно попытаться искать вхождение коротких слов типа " и ", " или ", ",а " в разных кодировках. Можно теоретически подобрать слово, а можно проверять кандидатуры на одном достаточно длинном тексте, перекодированном в разные кодировки, исключать тестовые слова, которые вызывают ложные срабатывания.

5 Три буквы

Взять любой достаточно объёмный текст на русском языке (можно архив lib.ru).

Написать скрипт, который составит список последовательностей из трёх букв, которые в этом тексте отсутствуют (хзь, ччй...). Дополнительно сделать скрипт поиска опечаток, который будет извлекать из текста слова, содержащие "невозможные" буквосочетания.

Если я правильно посчитал, то число сочетаний из трёх букв (включая Ё) равно 333333 т.е приблизительно 33000. Число вполне разумное и вычисление много времени и памяти не займёт.

6 quoted-printable1

Почтовая кодировка quoted-printable оставляет латинскую часть кодировки ASCII как есть, а однобайтные русские буквы, знак = и, иногда, пробел представляет в 16-ричном представлении вида =А6. Говорят, что в Ubuntu есть программа qprint для работы с этой кодировкой.

В CentOS такой команды нет, но есть команда xxd, которая конвертирует байты в их 16-ричное представление.

Написать программу, которая будет кодировать смешанный русско-английский текст в quoted-printable. Строго следовать стандарту не обязательно. Так, пробелы можно оставить пробелами, а также считать, что в тексте нет управляющих символов.

7 quoted-printable2

Почтовая кодировка quoted-printable оставляет латинскую часть кодировки ASCII как есть, а однобайтные русские буквы, знак = и, иногда, пробел представляет в 16-ричном представлении вида =А6. Говорят, что в Ubuntu есть программа qprint для работы с этой кодировкой.

В CentOS такой команды нет, но есть команда xxd, которая конвертирует байты в их 16-ричное представление.

Написать программу, которая из кодировки quoted-printable восстанавливает однобайтовую кодировку. Т.е. поcледовательность вида =E3 превращает в один байт со значением 0xE3

8 Кредитка1

Для проверки правильности номера банковской карты используется алгоритм Луна (ГОСТ ISO/IEC 7812-1-2014)

Контрольная цифра вычисляется на основе первых 15 цифр и записывается в 16 позицию

Алгоритм описывается так (в стандарте чуть иначе):

  1. удвоить значение каждой второй цифры, начиная с первой цифры слева
  2. если после шага 1 в данной позиции получилось двузначное число, то сложить его цифры между собой
  3. сложить результаты удвоения, полученные на этапе 2 и цифры исходного номера, не подвергшейся удвоению
  4. вычесть сумму, полученную на этапе 3, из следующего бОльшего числа, оканчивающегося на ноль.

Если сумма, полученная на этапе 3, является числом, оканчивающимся на ноль (30, 40 и т. п.), то контрольная цифра равна 0.

Написать скрипт подсчёта контрольной цифры 15-значного номера, полученного как аргумент.

9 Кредитка2

Для проверки правильности номера банковской карты используется алгоритм Луна (ГОСТ ISO/IEC 7812-1-2014)

Контрольная цифра вычисляется на основе первых 15 цифр и записывается в 16 позицию

Реализовать алгоритм проверки:

  1. удвоить значение каждой второй цифры, начиная с первой цифры слева
  2. если после шага 1 в данной позиции получилось двузначное число, то сложить его цифры между собой
  3. сложить результаты удвоения, полученные на этапе 2 и цифры исходного номера, не подвергшейся удвоению
  4. если последняя цифра равна нулю, то ошибок нет

Написать скрипт проверки правильности номера, полученного как аргумент.

10 Уникальные файлы

В большом каталоге с подкаталогами хранится архив файлов (например, фотоархив). Есть подозрение, что часть файлов была скопирована под другими именами.

Написать скрипт поиска одинаковых файлов. Критерием одинаковости является контрольная сумма, вычисленая программой sum.

Скрипт получает в качестве параметра имя каталога (или начинает с текущего если нет параметра) и печатает группы имен найденных файлов дубликатов. Группы разделяются пустыми строками.

11 Календарь

Напечатать календарь на текущий год. В первой строке месяца его название. Далее даты разбитые на строки по 7 дней недели. Первая строка имеет слева отступ, соответствующий дню недели, приходящемуся на 1 число. Субботу и воскресенье можно вывести на экран красным цветом.

2021 сентябрь 1 2 3 4 5 6 7 8 9 10

12 Игра "угадайка"

Человек задумывает число от 0 до 10. Программа задаёт вопросы на "больше"-"меньше":

Это число больше 7?
[y/n]
Это число меньше 2?
[y/n]

Человек отвечает да или нет, программа должна отгадать число.

13 Крестики-нолики

Надо написать программу, с которой можно играть в крестики-нолики. Программа запускается с параметром x или o, который указывает за кого она будет играть. Крестики ходят первыми.

Человек вводит, а скрипт в цикле читает строки с двумя цифрами . Первая цифра означает номер строки, вторая номер колонки. Т.к. это крестики нолики, то возможные цифры от 1 до 3. При неправильном вводе выдаётся ошибка и запрашивается новый ход. При правильном вводе он засчитывается за ход человека, делается ход программы, и рисуется поле 3х3 с текущей позицией. Под полем выдается приглашение на ввод следующего хода..

Алгоритм искусственного интеллекта можно использовать максимально простой — табличный. Все возможные позиции можно хранить в отдельном файле. Команда grep будет извлекать из этого файла оптимальный ход, соответствующий позиции.

Для чтения строк используется команда read, вывод на экран командой echo или printf.Можно стирать экран и рисовать только текущую позицию, а можно печатать очередную позицию после предыдущей, так что на экране останется история ходов.

14 Бэкап1

В одном из заданий в течение семестра была задача на инкрементальное архивирование командой tar. Предположим, что полный архив делается раз в 10 дней, а затем каждый день делается архивирование обновлённых за сутки файлов. В результате, у вас есть архивы с названиями такого вида:

dir-full-20220110.tar, dir-new-20220111.tar, dir-new-20220112.tar... dir-full-20220120.tar

Написать скрипт, который по имени файла (с путём) находит в архивах его самую свежую версию и выдаёт имя архива.

15 Бэкап2

В одном из заданий в течение семестра была задача на инкрементальное архивирование командой tar. Предположим, что полный архив делается раз в 10 дней, а затем каждый день делается архивирование обновлённых за сутки файлов. В результате, у вас есть архивы с названиями такого вида:

dir-full-20220110.tar, dir-new-20220111.tar, dir-new-20220112.tar... dir-full-20220120.tar

Написать скрипт, который по имени файла (с путём) печатает даты его изменений.

16 Почти шелл

Написать оболочку для работы с архивом tar, которая будет имитировать работу с файловой системой.

В задании для примера взят архив arch.tar. Текущий каталог можно хранить в файле archive.cwd (где archive совпадает с именем архива) Пусть скрипт называется fstar. Он должен реализовать следующие команды:

  • fstar ls arch.tar — список файлов текущего каталога.
  • fstar cd /directory arch.tar - смена текущего каталога в архиве
  • fstar cat file arch.tar - извлечение файла из архива в STDOUT
  • fstar cp archfile path/dstfile arch.tar - извлечение из архива файла archfile под именем path/dstfile
  • fstar cp srcfile path arch.tar - добавление файла srcfile в архив, приписав ему каталог path в архиве

Стеммер

Алгоритм нахождения корневых основ русского языка (стемминга) описан по ссылке - http://snowball.tartarus.org/algorithms/russian/stemmer.html

Задача — реализовать алгоритм на языке shell

Скриптовый вирус

Вот готовое описание скриптового вируса. Осталось его реализовать.

Вирус должен быть написан на языке shell. Он должен уметь заражать скрипты на языке shell через вставку в них своего кода.

Вирус содержит строки комментарии, обозначающие его начало и конец

#virus begin
virus body
#virus end
  • Вирус должен просмотреть все объекты в каталоге (цикл for).
  • У каждого объекта проверяется тип - является ли он файлом (test -f). Не файлы пропускаются.
  • У каждого файла проверяется доступен ли он на чтение и на запись (test -r, test -w). Недоступные файлы пропускаются.
  • У каждого файла проверяется наличие в первой строке подстроки "#!/bin/bash" (head -n 1, grep). Файлы без такой подстроки пропускаются.
  • В файле ищется сигнатура вируса #virus begin. Если файл уже заражен, то он пропускается.
  • Когда найден файл жертва, то вирус копирует его в каталог /tmp/.
  • Из аргумента $0 вирус узнает имя файла, из которого он был запущен, и копирует свое тело из этого файла в каталог /tmp/.
  • В тело файла жертвы записывается строка #!/bin/bash, затем тело вируса из каталога /tmp, затем оригинальный скрипт без первой строки из копии в каталоге /tmp.
  • Удаляются вспомогательные файлы в каталоге /tmp
  • После заражения одного файла вирус останавливается и передает управление родительскому скрипту.

File commander

Надо написать однопанельный клон нортон коммандера. Т.е. надо выводить на экран часть списка файлов в текущем каталоге. Одну из строк с именем файла помечать цветом или маркером в начале строки как текущую. Стрелками перемещать маркер и прокручивать список. По нажатию на Enter выполнять с текущим файлом некоторое действие в зависимости от его типа.

Предполагаем, что у нас нет имён файлов со спецсимволами (перевод строки, забой и т.п.), но могут быть имена файлов с пробелами.

Для управления вместо стрелок используем буквы. Например j-стрелка вниз, k- вверх, Enter или x - выполнить, q-завершить работу.

  • Определяем размеры экрана, начинаем основной цикл
  • Читаем список файлов и каталогов в текущем каталоге. Файлы, имена, которых начинаются с точки - игнорируем.
  • Имена файлов не вмещающихся в ширину экрана обрезаем
  • Печатаем на экране столько файлов, сколько входит, зарезервировав одену строку на ввод команды. Каталог .. печатаем в первой позиции. Каталог . не печатаем.
  • Перед каждым файлом печатаем два символа. Первый - тип: f-файл, d-каталог, x-исполняемый файл. Второй символ - курсор: обычно пробел, но для текущего файла - '>'
  • При нажатии клавиш вверх и вниз - курсор перемещается. При достижении последней строки, список файлов сдвигается вверх если "за экраном" есть файлы, то же при достижении верхней строки. Список файлов как бы находится за виртуальной прорезью размером с экран.
  • При нажатии на клавишу исполнения: на каталоге - переход в каталог, на исполняемом файле - запуск, на текстовом файле - запуск редактора.
  • Клавиша выхода - очистка экрана и выход.

Для чтения по одной букве используем read -n1. Для определения типа файла - file Определение размеров экрана - stty -a. управление экраном tput. Логика прокрутки списка файлов - самостоятельно.

Файлы для обработки