== Основы использования командной строки == === Для чего нужен командный интерпретатор? === Командный интерпретатор (или, на сленге, шелл --- от англ. ''unix shell'') выполняет 3 функции: * Предоставляет удобные средства для работы с командной строкой. Это, например, просмотр истории команд (клавиши "вверх" и "вниз"), поиск по истории команд (обычно Ctrl+R и Ctrl+S), дополнение команды и ее параметров по нажатию клавиши tab. * Предоставляет возможность комбинировать и интегрировать различные стандартные утилиты. Утилитами на сленге обычно называют небольшие программы из стандартного окружения unix-систем (от англ. ''util''), которые решают свою небольшую задачу, при этом получая данные и выдавая результат в текстовом виде. Перенаправление ввода-вывода позволяет реализовать совместную работу нескольких утилит, и, таким образом, решить некоторую более сложную пользовательскую задачу. Подобное удобство манипулирования утилитами предоставляет только командный интерпретатор, и именно это является его основной функцией. * И, наконец, командный интерпретатор --- это специализированный высокоуровневый язык программирования, ориентированный на операции с объектами файловой системы. === Переменные === Как в любом языке программирования, в шелле есть переменные. В силу особенностей назначения шелла все переменные в нем являются строковыми (при необходимости в арифметических операциях они временно преобразуются в целочисленные и обратно). Пример инициализации переменной. Заметьте, что при инициализации переменной до и после знака "=" не должно стоять пробелов, и что для получения значения переменной перед ее именем обязательно ставят символ "$", а имя может быть заключено в фигурные скобки для определенности. {{{ $ VAR="Value Value" $ echo $VAR Value Value $ echo VAR VAR $ echo "Переменная VAR : ${VAR} сейчас" Переменная VAR : Value Value сейчас }}} Переменные автоматически передаются всем программам, запущенным из шелла, в качестве части окружения созданного процесса операционной системы. Окружение процесса --- это набор достаточно разнообразной информации связанной с процессом. Туда входят, например, текущий каталог, дескрипторы открытых файлов, и т. п. При создании нового процесса путем копирования (''fork'') окружение практически полностью наследуется. Некоторые переменные, например HOME или PATH определяются при входе пользователя в систему в запускаемом при входе пользователя интерпретаторе (''login shell''), и от него наследуются всеми процессами, запущенными пользователем. Переменная PATH содержит список каталогов, в которых шелл ищет исполняемые файлы. {{{ $ echo $PATH /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin }}} Заметим, что в отличие от Windows, DOS и ранних версий UNIX, текущий каталог ("./") по соображениям безопасности в PATH не включен. Обратим внимание на значения переменных, содержащие пробел. Начнем с того, что при задании такого значения обязательно использование кавычек, иначе пробел будет считаться разделителем между инициализацией переменной и запуском команды: {{{ $ VAR="Value Value" $ echo "$VAR" Value Value $ echo $VAR Value Value }}} Как видно, при использовании кавычек значение сохраняется в первозданном виде. Без закавычивания несколько пробелов превращаются в один. ##первосданном -- это отлично = ) === Перенаправление ввода вывода === ## ">", "<", ">>" и "|" были названы в тексте операторами. В man bash они значаться как metacharacters, а "|" также названо operator (то есть операция, по обычному для языков программирования переводу). Для работы с файлами прикладные программы используют файловые дескрипторы. Как уже упоминалось, любая запущенная программа (то есть процесс операционной системы) имеет доступ к трем инициализированным перед ее запуском файловым дескрипторам. Они имеют следующие назначение, мнемонические обозначение и номер: * стандартный поток ввода stdin имеет номер 0; * стандартный поток вывода stdout имеет номер 1; * стандартный поток для сообщений об ошибках stderr имеет номер 2. # и иногда запускающий процесс Все прочие файловые дескрипторы, создаваемые программой, начинаются с номера 3. Подготовкой стандартных файловых дескрипторов занимаются операционная система, а запущенный процесс просто получает уже готовые к использованию дескрипторы и может сразу их использовать для файлового ввода-вывода. По умолчанию все три дескриптора ассоциируются с терминалом: ввод связан с клавиатурным вводом, а вывод и вывод ошибок выводят на экран. В качестве наглядной демонстрации удобства подобного подхода рассмотрим утилиту {{{cat}}}. Сама по себе она достаточно бессмысленна --- читает данные из stdin и выводит их в stdout. Поэтому, если пользователь при работе с ней наберет на клавиатуре "Hello" и Enter, то именно это слово и будет выведено на экран: {{{ $ cat Hello Hello }}} При работе с командной средой существует возможность при запуске каждой программы изменить поведение стандартных потоков, например, связав их с файлами. Шелл позволяет сделать это при помощи символов "<" , ">" и ">>", записываемых после параметров команды: * символ "<" перенаправляет стандартный потока ввода; * символ ">" перенаправляет стандартный потока вывода, затирая старое содержимое файла; * символы ">>" перенаправляют стандартный поток вывода, добавляя его содержимое в конец файла-аргумента. Рассмотрим следующие примеры использования перенаправления ввода-вывода в файл. {{{ $ # Здесь пользователь набирает "Hello" на клавиатуре: $ cat >> File Hello $ # А здесь выводит созданный файл на экран: $ cat < File1 Hello $ # Здесь пользователь набирает "Hello World" на клавиатуре: $ cat >> File1 Hello World $ # И еще раз выводит созданный файл на экран: $ cat < File1 Hello Hello World $ # Записываем "Hello?" в файл, затирая старое содержимое: $ echo "Hello?" > File1 $ cat < File1 Hello? $ # Копируем File1 в File2 через перенаправления ввода-вывода: $ cat < File1 > File2 $ cat File2 Hello? }}} Перед символами можно указать номер дескриптора для перенаправления. Таким образом, перенаправление стандартного потока ошибок в файл реализуется конструкцией "2>", например: {{{ $ script -t my_script 2> my_script.time }}} Например, у утилиты cat нет ключа --l, и если попытаться вызвать ее с ним, она выведет диагностическое сообщение в стандартный поток ошибок. {{{ $ cat --l < File1 > File3 2> Error $ cat Error cat: нераспознанный ключ `--l' }}} Если мы хотим поместить в один файл и сообщения об ошибках, и стандартный вывод программы, то можно использовать конструкцию "&>". Следующая команда поместит в файл File3 сообщение о невозможности прочитать файл {{{/etc/shadow}}} и содержимое файла {{{/etc/passwd}}}. {{{ $ cat /etc/shadow /etc/passwd &> File3 }}} Еще более интересным и многообещающим является возможность ассоциирования стандартного потока вывода одной программы с стандартным потоком ввода другой. В командном интерпретаторе эта операция организуется символом "|" ( для реализации этой функциональности на системном уровне обычно используются безымянные каналы). Программа {{{cal}}} выводит календарь на месяц. Если с потоком вывода проассоциирован терминал, то {{{cal}}} раскрашивает текущий день. В противном случае выводится просто текст. Например, при вызове {{{cal | cat}}} выделения цветом не будет, так как потоком вывода для cal будет безымянный канал. {{{ $ cal | cat Июль 2008 Вс Пн Вт Ср Чт Пт Сб 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 }}} Утилита {{{wc}}} без параметров выводит количество символов, слов и переводов строк в стандартном потоке ввода. {{{ $ cal | wc 8 40 186 }}} Можно делать более длинные конвейеры, например {{{cal | tac | tac}}}. Утилита tac выводит поступившие ей строки в обратном порядке, так что, если применить её два раза, ничего не произойдёт: {{{ $ cal | tac | tac Июль 2008 Вс Пн Вт Ср Чт Пт Сб 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 }}} Утилита {{{head}}} выводит заданное количество первых строк ввода, {{{tail}}} --- последних. Комбинируя эти утилиты, можно получить произвольный срез файла по строкам): {{{ $ cal | head -2 | tail -1 Вс Пн Вт Ср Чт Пт Сб }}} Перенаправление --- очень эффективный интрумент, использующийся практически в любом сценарии на языке Shell. === Генерация списка файлов по шаблону === ## В оригинале вместо ls было echo по неясным причинам. Для групповых операций с файлами командный интерпретатор позволяет использовать регулярные выражения для задания группы файлов. Используется стандартная нотация, поддерживаются диапазоны. Примеры: {{{ $ # Файлы, начинающиеся с "F": $ ls F* File1 File2 File3 File4 File45 File678 $ # Файлы с именами из "File" и двумя символами после: $ ls File?? File45 $ # "[2-4]" означает диапазон из 2, 3, 4: $ ls File[2-4] File2 File3 File4 $ # ^ означает инверсию, "[^2-4]" --- один символ не из диапазона 2-4: $ ls File[^2-4] File1 $ # "[2-46*]" --- символ 2, 3, 4, 6 или "*": $ ls File[2-46*] File2 File3 File4 $ # "[2-46]*" --- 2, 3, 4 или 6, после которых может идти что угодно: $ ls File[2-46]* File2 File3 File4 File45 File678 }}} При использовании генерации имен файлов в unix-системах не следует забывать, что выполняет ее именно командный интерпретатор, а не вызываемая программа. Это может вызывать неудобства в ряде случаев. Так же надо обратить внимание, что файлы, имя которых начинается с точки (".") по умолчанию не включаются в генерируемые списки, соответствующие шаблону "*", а под ".*" попадают далеко не всегда нужные каталоги "." и "..": {{{ $ ls .* . .. .FileFile .FileFileFile }}} Общего удобного решения этой проблемы не существует. В частных случаях можно попробовать воспользоваться исключением: {{{ $ ls .[^.]* .FileFile .FileFileFile $ ls .[^.]* * .FileFile .FileFileFile File1 File2 File3 File4 File45 File678 }}} В качестве еще одного неудобного следствия генерации списков файлов следует отметить то, что программа не может отличить ключ от имени файла: {{{ $ # Cоздаем файл c именем -l $ echo 1 > -l $ ls File1 File2 File3 File4 File45 File678 -l $ # А здесь ls "думает", что ее вызвали с ключом -l: $ ls * -rw-r--r-- 1 user user 1 2008-08-01 08:14 File1 -rw-r--r-- 1 user user 1 2008-08-01 08:15 File2 -rw-r--r-- 1 user user 1 2008-08-01 08:15 File3 -rw-r--r-- 1 user user 1 2008-08-01 08:15 File4 -rw-r--r-- 1 user user 1 2008-08-01 08:15 File45 -rw-r--r-- 1 user user 1 2008-08-01 08:16 File678 }}} Ряд программ, принимающих в качестве аргументов имена файлов, в том числе большинство из состава набора программ coreutils, учитывают эту особенность и позволяют указать специальный аргумент `--`, который символизирует то, что список опций завершён и все дальнейшие аргументы следует трактовать как имена файлов. ---- === Сведения о ресурсах === ## ВНИМАНИЕ! Поля значащие, просьба редактироать только числа и списки модулей ## Требования к знаниям слушателя — имена модулей через пробел; если нет — пустая ячейка ## Ментейнеры прописываются в сответствии с PspoTasks || Готовность (%) || Продолжительность (ак. ч.) || Подготовка (календ. ч.) || Полный текст (раб. д.) || Предварительные знания || Level || Maintainer || Start date || End date || || 90 || 1 || 1 || 1 || || 1 || MaximByshevskiKonopko, [[Allena]], VsevolodKrishchenko || || || ---- CategoryLectures CategoryPspo CategoryMpgu CategoryUneex