1.2. Командна мова shell
Командна мова shell (у перекладі – раковина, шкарлупа) фактично є мовою програмування дуже високого рівня. На цій мові користувач здійснює керування комп’ютером. Звичайно, після входу в систему ви починаєте взаємодіяти з командною оболонкою. Ознакою того, що оболонка (shell) готова до прийому команд служить рядок, що видається нею на екран. У найпростішому випадку це один долар (“$”).
Shell не є необхідною і єдиною командною мовою (хоча саме вона стандартизована у рамках POSIX [POSIX 1003.2] – стандарти мобільних систем). Наприклад, чималою популярністю користується мова cshell, є також kshell, bashell (з найбільш популярних останнім часом) і інші. Більш того, кожний користувач може створити свою командну мову. Може одночасно на одному екземплярі операційної системи працювати з різними командними мовами.
Shell – це одна з багатьох команд Linux. Тобто в набір команд оболонки (інтерпретатора) “shell” входить команда “sh” – виклик інтерпретатора “shell”. Перший “shell” викликається автоматично при вході в систему і видає на екран командний рядок. Після цього ви можете викликати на виконання будь-які команди, у тому числі й знову сам “shell”, що вам створить нову оболонку усередині колишньої.
Основним елементом мови shell є команда.
Структура команд. Команди в shell звичайно мають наступний формат:
<ім’я команди> <прапори> <аргумент(и)>
Наприклад:
ls – ls /usr/bin
Ця команда видасть на екран у довгому форматі вміст директорії /usr/bin, при цьому додасть інформацію про розмір кожного файла в блоках.
На жаль, така структура команди дотримується далеко не завжди. Не завжди перед прапорами ставиться мінус, не завжди прапори йдуть одним словом. Є розмаїтість і в поданні аргументів. До числа команд, що мають екзотичні формати, належать й такі “ходові” команди, як сс, tar, dd, find і ряд інших.
Як правило (але не завжди), перше слово (тобто послідовність символів до пробілу, табуляції або кінця рядка) shell сприймає, як команду. Тому в командному рядку
cat cat
перше слово буде розшифроване shell, як команда (конкатенації), що видасть на екран файл із ім’ям “cat” (друге слово), що знаходиться в поточній директорії.
Групування команд. Засоби групування:
; і <переведення рядка> – визначають послідовне виконання команд;
& – асинхронне (фонове) виконання попередньої команди;
&& – виконання наступної команди за умови нормального завершення попередньої, інакше ігнорувати;
|| – виконання наступної команди при ненормальному завер-шенні попередньої, інакше ігнорувати.
При виконанні команди в асинхронному режимі (після команди стоїть один амперсант) на екран виводиться номер процесу, що відповідає виконуваній команді, і система, запустивши цей фоновий процес, знову виходить на діалог з користувачем.
Наприклад, наберемо команду “find” у фоновому режимі для пошуку в системі, починаючи від кореня “/”, файла з ім’ям “conf”, а потім “pwd” у звичайному режимі. На екрані цей фрагмент буде виглядати наступним чином:
$ find / -name conf -print & введення команди “find”
288 номер (PID) фонового процесу
$ pwd введення команди “pwd”
/mnt/lab/asu результат роботи “pwd”
$ повернення shell у промптер
/usr/include/sys/conf результат роботи “find”
Для групування команд також можуть використовуватися фігурні “{}” і круглі “()” дужки. Розглянемо приклади, що поєднують різні способи групування: Якщо введено командний рядок
k1 && k2; k3
де k1, k2 і k3 – якісь команди, то “k2” буде виконана тільки при успішному завершенні “k1”; після кожного з результатів обробки “k2” (тобто “k2” буде виконана, або пропущена) буде виконана “k3”.
k1 && {k2; k3}
Тут обидві команди (“k2” і “k3”) будуть виконані тільки при успішному завершенні “k1”.
{k1; k2} &
У фоновому режимі буде виконуватися послідовність команд “k1” і “k2”.
Фонові процеси складно знищити, оскільки традиційна команда “CTL/C” перериває тільки процеси переднього плану. Для знищення фонового процесу треба знати його номер. При запуску фонового процесу на екран видається число, що відповідає номеру (ідентифікатору) цього процесу (PID). Якщо цей номер забутий або треба переконатися, що цей процес не закінчений, за допомогою команди
ps – aux
можна одержати перелік ідентифікаторів процесів (PID), імена користувачів, поточний час, витрачений процесами, і т.д.
У виведеній таблиці можна знайти номери процесів, що підлягають знищенню, наприклад, “849” і “866”. Тоді командою
kill – 9 866 849
можна знищити ці процеси. При знищенні процесів ви повинні мати те саме ім’я користувача, яке було приписано знищуваним процесам (або мати ім’я привілейованого користувача).
Круглі дужки “()”, крім виконання функції групування, виконують і функцію виклику нового екземпляра інтерпретатора shell.
Нехай ми знаходилися в початковому каталозі “/mnt/lab/asu”. Тоді в послідовності команд
cd ..; ls; ls
дві команди “ls” видадуть два екземпляри вмісту каталогу “/mnt/lab”, а послідовність
(cd ..; ls) ls
видасть спочатку вміст каталогу “/mnt/lab”, а потім вміст “/mnt/lab/asu”, тому що при вході в дужки викликається новий екземпляр shell, у рамках якого й здійснюється перехід. При виході із круглих дужок відбувається повернення в старий shell і в старий каталог.
Перенаправлення команд. Стандартне введення (вхід) – “stdin” в ОС Linux здійснюється із клавіатури термінала, а стандартний вивід (вихід) – “stdout” спрямований на екран термінала. Існує ще й стандартний файл діагностичних повідомлень – “stderr”.
Команда, що може працювати зі стандартним входом і виходом, називається фільтром.
Користувач має зручні засоби перенаправлення введення і виводу на інші файли (пристрої). Символи “>” і “>>” позначають перенаправлення виводу.
ls >f1
Команда “ls” сформує список файлів поточного каталогу і помістить його у файл “f1” (замість видачі на екран). Якщо файл “f1” до цього існував, то він буде затертий новим.
pwd >>f1
Команда pwd сформує повне ім’я поточного каталогу і помістить його в кінець файла “f1”, тобто “>>” додає у файл, якщо він непустий.
Символи “<” і “<<” позначають перенаправлення введення.
wc – l <f1
підрахує і видасть на екран число рядків у файлі f1.
ed f2 <<!
створить із використанням редактора файл “f2”, безпосередньо з термінала. Закінчення введення визначається за символом, що стоїть справа від “<<” (тобто “!”). Тобто введення буде завершено, коли першим у черговому рядку буде “!”.
Можна поєднувати перенаправлення. Так
wc – l <f3 >f4 і wc – l >f4 <f3
виконуються однаково: підраховується число рядків файла “f3” і результат поміщається у файл “f4”.
Засіб, що поєднує стандартний вихід однієї команди зі стандартним входом іншої, називається конвеєром і позначається вертикальною рискою “|”.
ls | wc – l
Список файлів поточного каталогу буде спрямований на вхід команди “wc”, що виведе на екран число рядків каталогу.
Конвеєром можна об’єднувати і більше двох команд, коли всі вони, можливо крім першої й останньої – фільтри:
cat f1 | grep – h result | sort | cat – b > f2
Цей конвеєр з файла “f1” (“cat”) вибере всі рядки, що містять слово “result” (“grep”), відсортує (“sort”) отримані рядки, а потім пронумерує (“cat –b”) і виведе результат у файл “f2”.
Оскільки пристрої в ОС Linux представлені спеціальними файлами, їх можна використовувати при перенаправленні. Спеціальні файли знаходяться у каталозі “/dev”. Наприклад, “lp” – друк; “console” – консоль; “ttyi” – i-й термінал; “null” – фіктивний (порожній) файл (пристрій).
Тоді, наприклад,
ls > /dev/lp
виведе вміст поточного каталогу на друк, а f1 < /dev/null обнулить файл “f1”.
sort f1 | tee /dev/lp | tail – 20
У цьому випадку буде відсортований файл “f1” і переданий на друк, а 20 останніх рядків також будуть видані на екран.
Повернемося до перенаправлення виходу. Стандартні файли мають номера: 0 – stdin, 1 – stdout і 2 – stderr. Якщо вам не бажано мати на екрані повідомлення про помилку, ви можете перенаправляти його з екрана в зазначений вами файл (або взагалі “викинути”, перенаправивши у файл “порожнього пристрою” – /dev/null). Наприклад, при виконанні команди cat f1 f2, яка повинна видати на екран послідовний вміст файлів “f1” і “f2”, видасть вам, наприклад, наступне:
111111 222222
cat: f2: No such file or directory
де 111111 222222 – вміст файла “f1”, а файл “f2” відсутній, про що команда “cat” видала повідомлення в стандартний файл діагностики, за замовчуванням, як і стандартний вихід, представлений екраном.
Якщо вам не бажане таке повідомлення на екрані, його можна перенаправляти в зазначений вами файл:
cat f1 f2 2>f-err
Повідомлення про помилки будуть направлятися (про це говорить перенаправлення “2>”) у файл “f-err”. До речі, ви можете всю інформацію направляти в один файл “ff”, використавши в цьому випадку конструкцію
cat f1 f2 >>ff 2>ff
Можна вказати не тільки який зі стандартних файлів перенаправляти, але й у який стандартний файл здійснити перенаправлення.
cat f1 f2 2>>ff 1>&2
Тут спочатку “stderr” перенаправляється (у режимі додавання) у файл “ff”, а потім стандартний вихід перенаправляється на “stderr”, яким до цього моменту є файл “ff”. Тобто результат буде аналогічний попередньому.
Довідкові команди
Команда date застосовується для визначення поточної дати та часу.
Команда who дозволяє отримати список користувачів, що працюють в системі в даний момент часу.
Наприклад:
$ who
petr tty4i Mar 11 18:46
ann tty12 Mar 11 16:29
Виводиться ім’я користувача, номер термінала, дата і час початку роботи цього користувача. Команда who am i виводить інформацію про самого користувача.
Команда man застосовується для друку окремих розділів з керівництва по операційній системі Linux. Формат її застосування:
$ man [ім’я команди]
Наприклад, допомогу по команді ls можна вивести командою man ls.
Альтернативою команди man в деяких версіях системи Linux є команда use:
use [ім’я команди]
Команди роботи з каталогами. Команда pwd призначена для друку імені поточного каталогу. Формат: pwd
Наприклад:
$ pwd
/usr/work/petr
Команда ls призначена для друку імен файлів, що містяться в каталозі, та іншої інформації про них. Файли можуть бути як, власне, файлами, так і каталогами. Якщо ім’я каталогу не вказано, то виво-диться вміст поточного каталогу.
Формат: ls [аргументи] [ім’я..]
Аргументи:
-f – надрукувати лістинг довгого формату;
-t – впорядкувати список файлів по часу модифікації;
-a – включити в список файлів всі файли, імена яких починаються з крапки;
-s – надрукувати розміри файлів в блоках;
-d – надрукувати інформацію по кожному каталогу;
-c – надрукувати в багатостовпцевому вигляді;
-r – вивести вміст вкладених каталогів;
-m – надрукувати вміст каталогу через кому.
Приклад:
$ ls –l
total 5
drwxrwxrwx |
6 |
petr |
user1 |
496 |
Mar 10 12:01 |
tmp |
-rw-rw-r-- |
1 |
petr |
user1 |
156 |
Mar 12 15:26 |
file.c |
-rwxrwx--x |
2 |
root |
root |
4003 |
Apr 01 11:44 |
pe.out |
Команда cd призначена для переходу з одного каталогу в інший. При цьому вказаний каталог стає поточним. Команда cd без аргументів відновлює як поточний початковий каталог користувача.
Формат: cd [каталог]
Приклади:
перейти в каталог: cd dd/ddd1;
перейти в батьківський каталог поточного каталогу: cd .. ;
перейти в кореневий каталог користувача: cd або cd ~.
Команда mkdir – створити каталог
Формат: mkdir [-ключі] ім’я_каталогу
Для реалізації цієї команди вимагаються права запису в батьківський каталог. При створенні каталогу автоматично заносяться файли ’.’ і ’..’.
Команда rmdir – видаляє каталоги.
Формат: rmdir ім’я_каталогу.
Команда rmdir видаляє тільки порожні каталоги. Згідно визначення порожнім вважається каталог, що містить тільки два елементи ’.’ і ’..’. Система не дозволить видалити каталог, якщо у користувача немає прав запису у нього. Поточний каталог не повинен належати піддереву каталогів, що видаляються.
Команда df – визначає вільний дисковий простір.
Команда df без аргументів виводить наступну багатостовпцеву інформацію:
– перша колонка – точки монтування файлової системи, тобто каталог монтування фізичного пристрою, наприклад / або /home;
– друга колонка – монтований фізичний пристрій, тобто файл, зв’язаний з фізичним пристроєм (наприклад, з жорстким диском /dev/hdb1);
– третя колонка – лічильник вільних блоків по 512 байт;
– четверта колонка – кількість файлів;
Команда df -k виводить наступну багатостовпцеву інформацію:
– перша колонка – імена монтованих фізичних пристроїв;
– друга колонка – дійсний розмір файлів системи в 1024-байтних блоках;
– третя колонка – лічильник використаних блоків по 1024 байти;
– четверта колонка – лічильник вільних блоків по 1024 байти;
– п’ята колонка – відсоток використання дискового простору;
– шоста колонка – монтування файлової системи.
Команди роботи з файлами
Команда rm – видалення файлів (посилань на файли). Ця команда видаляє посилання на файли (тобто локальні імена файлів), якщо у користувача є право запису в каталог, що містить ці імена. Якщо файл, що видаляється, захищений від запису, команда видає запит на видалення файла.
Формат: rm [-ключі] список
Ключі:
-f – скасовує необхідність підтвердження для кожного файла, що видаляється;
-i – вводить необхідність підтвердження для кожного файла, що видаляється;
-r – задає режим рекурсивного видалення всіх файлів і підкаталогів даного каталогу, а потім і самого каталогу.
Приклади
rm -i all – видаляє файл all з дозволу користувача.
rm -r alpha/ – видаляє всі файли в директорії alpha разом з директорією alpha.
Команда cat – об’єднання і виведення файлів на стандартний пристрій виведення. Команда по черзі читає вказані вхідні файли, якщо їх декілька, об’єднує і виводить прочитані дані в стандартний потік виведення (на екран). За допомогою перенаправлення потоків команда може бути використана для виконання різноманітних операцій.
Формат: cat [-ключі] [вхідний_файл1 [вхідний_файл2…]]
Приклади
$ cat > file1 – в файл file1 розміщується текст, що набирається на клавіатурі. Якщо до цього файл file1 не існував, він буде створений; якщо існував, його початковий вміст буде втрачено. Завершення введення тексту відбувається при натискані комбінації клавіш Ctrl+D.
$ cat file1 > file2 – вміст файла file1 копіюється в файл file2. Файл file1 при цьому залишається без змін.
$ cat file1 file2 > result – вміст file2 буде добавлено до вмісту file1 і розміщено в файлі result.
$ cat file1 >> file2 – вміст файла file1 додається в кінець файла file2.
Команда cp призначена для копіювання файлів.
Формат: cp [-i] файл (и) _джерело файл (директорія) _приймач.
-i – запит на перезапис існуючого файла.
Ця команда має два режими використання:
1) якщо вихідний файл є звичайним файлом, то вхідний файл може бути тільки один. Його вміст копіюється у вихідний файл. Якщо вихідний файл існував, то його старий вміст втрачається, а атрибути захисту залишаються. Якщо вихідний файл не існував, то він буде створений і наслідує атрибути вхідного файла.
2) якщо вихідний файл є каталогом, то в нього скопіюються всі вказані вхідні файли, але каталог повинен бути створений раніше.
Приклади
cp prefix.one.two big.f – копіює файл prefix.one.two в файл big.f. Якщо файл big.f існує, то він перезаписується.
cp many.txt ~/tmp – копіює файли c префіксом many.txt в директорію tmp, розташовану в кореневій директорії користувача.
Команда mv призначена для переміщення або перейменування файлів. Відмінність команди переміщення від команди копіювання полягає в тому, що вхідні файли після виконання команди знищуються.
Формат: mv [-i] файл (и) _джерело файл (директорія) _приймач
-i – запит на перезапис існуючого файла.
Приклад
mv test.text testing.text – перейменування файла test.text в testing.text. Якщо такий файл існує, то він перезаписується без попередження.
Команда ln створює нові посилання на файл (створює декілька імен для одного файла).
Формат: ln –s файл1 файл2 – перше ім’я файл1 стає новим ім’ям файл2.
Ця команда має два способи використання:
1) якщо вихідний файл є звичайним файлом, то вхідний файл може бути лише один. В цьому випадку на нього створюється посилання з іменем вихідного файла і до нього можна звертатися за обома іменами. Кількість посилань на файл в описі збільшується на 1.
2) якщо вихідний файл є каталогом, то в ньому створюються елементи, що включають імена всіх перерахованих вхідних файлів і посилань на них.
Приклад
$ ls
file1
$ ln file1 file2
$ ls
file1
file2
Команди роботи з текстовими файлами
Команда grep – здійснює пошук шаблона (рядка) в файлах. Формат використання:
grep [-ключі] рядок список_файлів
Знайдені рядки виводяться у стандартний пристрій виводу у форматі, що визначається ключами. Якщо файлів декілька, то перед кожним рядком виводиться ім’я відповідного файла.
Ключі:
-c – виведення імен всіх файлів з вказівкою кількості рядків, що містять шаблон;
-i – ігнорування регістру (відмінність рядкових і прописних латинських літер);
-n – виведення перед рядком його відносного номера в файлі;
-v – виведення рядків, що не містять шаблона (інверсія виведення);
-l – виведення тільки імен файлів, що містять шаблон.
Команда wc – виконує підрахунок кількості рядків, слів и символів в файлах. Формат використання:
wc [-lwc] [список_файлів]
Ключі:
-l – підрахунок рядків;
-w – підрахунок слів;
-c – підрахунок символів (за замовчуванням – lwc).
Якщо список файлів пустий, то підрахунок ведеться в стандартному потоці введення.
Команда sort – проводить сортування файлів. Формат використання:
sort [-ключі] список_файлів
Ця команда сортує вхідні файли за рядками у відповідності до збільшення кодів символів.
Ключі:
-r – обернений порядок сортування;
-f – не враховувати відмінність рядкових и прописних латинських літер;
-n – числовий порядок сортування.
Команда cmp – виконує порівняння файлів із виведенням позиції першого розходження. Формат використання:
cmp файл_1 файл_2
виводить номер символу і номер рядка (в текстових файлах), в якому вперше зустрічається розходження у вхідних файлах. Команда працює з будь-якими файлами.
Команда diff – виконує порівняння файлів і виведення всіх розбіжностей в файлах. Формат використання: diff файл_1 файл_2 виво-дить усі рядки, в яких зустрічаються розбіжності між вхідними файлами. Ця команда працює тільки з текстовими файлами.
Команда od призначена для виводу на друк вмісту заданих в ній файлів. За замовчуванням виводиться в вісімкових словах.
Формат: od [формат] файл
-b – вивід байтів в вісімковому форматі;
-c – вивід в коді ASCII;
-d – вивід в десятковому форматі;
-о – вивід слів в вісімковому форматі;
-x – вивід слів в шістнадцятковому форматі;
Команда find призначена для пошуку в означеному каталозі і його підкаталогах файлів, що мають задану властивість.
Формат: find [каталог] [властивість]
Команда послідовно переглядає всі підкаталоги, що починаються з одного із каталогів, вказаних в списку каталогів, аналізує їх атрибути і, якщо вони задовольняють умовам пошуку, виконує дії, задані в умовах пошуку.
У команді може бути задана множина умов пошуку, необхідні комбінації яких поєднуються у булевські вирази за допомогою логічних операцій:
! умова – заперечення умови;
пробіл – відповідає операції “ТА”;
-o – операція “АБО”;
(\вираз \) – булевський вираз в дужках.
Приклади
find / -type f -links +1 –print – виводяться повні імена файлів кореневого каталогу, на які є більш ніж одне посилання.
find / -type f -size +2 -exec ls -l {}\ – виводяться лістинги із вказівкою довжини в блоках по 1024 байти для файлів кореневого каталогу, довжина яких в блоках по 512 байт більше 2.
find / -name ‘*.a’ -exec ar -t {} \; |grep console
У цій складній програмі ведеться пошук файлів з розширенням ‘.а’, відбувається їх перегляд і виводяться рядки, що містять підрядок ‘console’.
Права доступу. Система розмежовує права доступу до файла для трьох класів користувачів: індивідуального власника файла, групового власника та інших користувачів.
Будь-який з файлів має певного власника і прив’язаний до деякої групи. Під групою розуміється безліч користувачів, об’єднаних за якоюсь ознакою, наприклад, співробітники підрозділу, розробники проекту. Рівень групової безпеки дозволяє поділяти спільні ресурси (доступ на читання, запис або виконання).
Рівень безпеки для інших користувачів визначає доступ до ресурсів всіх користувачів. Якщо деякому файлу надано право на читання для інших користувачів, то до нього може звернутися хто завгодно.
Кожному класу виділені певні права на читання, запис і виконання файлів, що встановлюються індивідуально. Оскільки каталоги, як файли, не можуть бути виконані, дозвіл на виконання у цьому випадку інтерпретується як право робити пошук в каталозі за іменем файла.
Права доступу до файла регулюються встановленням спеціальних бітів дозволу доступу, зв’язаних з файлом. Встановлюючи біт дозволу доступу, можна незалежно керувати видаванням дозволу на читання, запис і виконання для трьох категорій користувачів. Користувачі можуть створювати файли, якщо дозволений доступ до каталогу.
Отримання докладної інформації про кожний файл в каталозі робиться командою ls -l.
Перед списком файлів виводиться кількість блоків, що ви-користовуються файлами. Далі виводяться колонки.
Перша колонка: перший символ – вимірювач прав доступу:
– d – для каталогу;
– b – для спеціальних блокових пристроїв;
– c – для спеціальних символьних пристроїв;
Далі 9 символів – показники прав доступу до файла, розбиті на 3 групи по 3 символи. Права доступу для власника, для групи і для інших користувачів для кожної з трьох груп.
Перший символ r – файл доступний для читання;
Другий символ w – файл доступний для запису;
Третій символ x – файл, що виконується;
Четвертий символ s – файл виконуваний і даний користувач володіє власністю на даний файл;
Друга колонка – число зв’язків файла.
Третя колонка – власник файла.
Четверта колонка – група, що володіє файлом.
П’ята колонка – час останньої модифікації.
Шоста колонка – назва файла.
Управління правами доступу здійснюється командою chmod.
Формат: chmod ID_доступу file …
chmod _користувач {+, – або =} доступ file …
ID_доступу – число (ідентифікатор), що означає доступ до файла:
4000 – настанова на виконання користувачу;
2000 – настанова на виконання групі;
0400 – права читання власником;
0200 – права запису власником;
0100 – права виконання або пошуку власником;
0040 – права читання групою;
0020 – права запису групою;
0010 – права виконання або пошуку групою;
0004 – права читання іншими користувачами;
0002 – права запису іншими користувачами;
0001 – права виконання або пошуку іншими користувачами.
Можливе комбінування цих ідентифікаторів.
_користувач – символічний опис користувача:
u – користувач (власник);
g – група;
o – всі інші;
a – користувач, група і всі інші.
Якщо користувач не вказаний, то за замовчуванням приймається ’a’.
Операції:
– видалення означених доступів;
+ додавання означених доступів;
= очистка встановлених доступів і присвоєння означених;
Доступ:
r – доступ для читання;
w – доступ для запису;
x – доступ для виконання, доступ для пошуку по директоріям;
X – доступ для виконання, якщо file директорія.
Приклади
chmod g+w chap1 chap4 – додає доступ для групи для файлів chap1 і chap2.
chmod go-w+x mydir – додає доступ для виконання файлів в директорії mydir групі і іншим користувачам, і забороняє запис в неї. Це еквівалентно наступній послідовності команд:
chmod g-w mydir
chmod o-w mydir
chmod g+x mydir
chmod o+x mydir
chmod 644 text – (0400+0200+0040+0004) встановлює доступи для читання і запису для власника, доступи тільки для читання групі і іншим користувачам для файла text.
Використання шаблонів у командах. Метасимволи – символи, що мають спеціальне значення для інтерпретатора. До них належать: ? * ; & ( ) | ^ < > <пробіл> <табуляція> <повернення_каретки>.
Проте кожний із цих символів може представляти і самого себе якщо перед ним стоїть “\”. Всі символи, взяті в одинарні лапки ‘’ являють самих себе. Якщо вони взяті в подвійні лапки “”, то виконується підстановка команд і параметрів, а символи \, ‘,” и $ можуть екрануватись за допомогою символу “\”.
Після всіх підстановок в кожному слові команди відбувається пошук символів *, ? і [. Якщо зустрічається хоча б один із них, то це слово розглядається як шаблон імен файлів і замінюється іменами файлів, що відповідають цьому шаблону (в алфавітному порядку).
Якщо жодне ім’я файла не відповідає шаблону, то він залишається незмінним.
Значення вказаних символів:
* – будь-який рядок (послідовність символів), включаючи і порожній;
? – один будь-який символ;
[...] – будь-який із вказаних між ними символів. Пара символів, розділених знаком “–“, означає будь-який символ, який знаходиться між ними, включаючи і ці символи. Якщо перший символ після “[“ є “!”, то вказані символи не повинні входити в ім’я файла.
Наприклад, [a-de] еквівалентне [abcde].
Командна підстановка. Будь-який командний рядок може бути поміщений всередину зворотних лапок (‘...’), в результаті чого вивід цього командного рядка замінить при виконанні сам цей рядок. Це називається командна підстановка. Команда або команди, укладені в зворотні лапки, обробляються Shell в першу чергу, і їхній вивід замінює самі ці команди і зворотні лапки. Ця властивість часто використовується для присвоєння значень змінним Shell.
Today = ‘date’ – присвоює рядок зі значенням поточної дати змінній today (наприклад, “Tue Nov 26 16: 01: 09 EST 2003”). Наступна команда зберігає число в системі користувачів, що зареєструвалися, в змінній users:
users= ‘who|wc –l’
Будь-яка команда, що пише в стандартний вивід, може бути укладена в зворотні лапки. Зворотні лапки можуть бути вкладені одні в інші, але при цьому внутрішні повинні відділятися зворотними косими рисками (\), наприклад:
logmsg= ‘echo Your login directory is\’pwd\”
покаже рядок “Your login directory is (ім’я вашого каталогу)”.
Змінним Shell також можна присвоювати значення, використовуючи команди read і line.
Команда read зчитує рядок з стандартного вводу (звичайно з терміналу) і присвоює окремі слова всім означеним змінним.
Змінні Shell. В Shell є декілька засобів створення змінних. Змінна – це ім’я, якому присвоєне деяке значення. Деякі змінні є позиційними параметрами – їх значення встановлюються тільки в командному рядку. Інші змінні – це просто імена, яким користувач або сам інтерпретатор присвоїв текстові значення.
Для позначення змінних shell використовується послідовність літер, цифр і символів підкреслення; змінні не можуть починатися із цифри. Присвоювання значень змінним проводиться з використанням знака =, наприклад, PS2 = ‘<’ . Для звертання до значення змінної перед її ім’ям ставиться знак $. Їх можна розділити на наступні групи:
позиційні змінні вигляду $n, де n – ціле число;
прості змінні, значення яких може задавати програміст, користувач, або вони можуть встановлюватися інтерпретатором;
спеціальні змінні # ? – ! $ встановлюються інтерпретатором і дозволяють отримати інформацію про число позиційних змінних, код завершення останньої команди, ідентифікаційний номер поточних і фонового процесів, про поточні прапори інтерпретатора shell.
Прості змінні. Інтерпретатор Shell також розпізнає літерно-цифрові змінні, яким присвоєні текстові значення. Проста команда присвоєння має синтаксис:
Ім’я_змінної=значення
Після присвоєння при вказівці $ім’я_змінної буде видаватися значення рядка. Пропуски навколо знаку рівності (=) в команді присвоєння неприпустимі. Позиційні параметри таким способом визначити не можна; вони можуть встановлюватися тільки командою set.
У команді присвоєння може бути більш одного присвоєння, але треба пам’ятати, що Shell присвоює значення змінним справа наліво. Так, в результаті виконання наступного командного рядка
A=$B B=abc
змінній А буде присвоєне значення “abc”.
Нижче наводяться приклади простих присвоєнь. Подвійні лапки з правої сторони команди присвоєння дозволяють вказувати пропуски, знаки табуляції, символи переходу на новий рядок і крапки з комою в тексті, що присвоюється, а також виконувати підстановку змінних. Це означає, що при відкритті позиційних параметрів і інших імен змінних, перед якими стоїть знак $, вони будуть замінюватися на відповідні значення, якщо вони є. Одинарні лапки скасовують підстановку змінних:
MAIL=/usr/mail/gas
echovar=“echo $1 $2 $3 $4”
stars=*****
asterisks=‘$stars’
У наведених прикладах змінній echovar присвоєне значення рядка, що складається з слова echo і чотирьох позиційних параметрів, поділених пропусками. Навколо послідовності зірочок, що присвоюються змінній stars, дужок не вимагається, тобто їхнє спеціальне значення тут не діє. Зверніть увагу, що змінній asterisks присвоєне текстове значення ‘$stars’, а не “*****”, оскільки одинарні лапки скасували підстановку.
У командах присвоєння при підстановці пропуски повторно не інтерпретуються, тому змінні $first і $second в наступному прикладі мають одне і те саме значення:
first=‘a string with embedded spaces’
second=$first
У разі звертання до значень змінних ви можете поміщати ім’я змінної у фігурні дужки, щоб відділити ім’я змінної від іншого тексту. А саме, якщо символ, що йде безпосередньо після імені, є літерою, цифрою або знаком підкреслення, фігурні дужки необхідні. Наприклад:
a= ‘This is a string’
echo “${a}ent test of variables.”
У цьому випадку команда echo надрукує:
This is a stringent test of variables.
Позиційні змінні. Змінні виду $n. де n – ціле число, використовуються для ідентифікації позицій елементів у командному рядку за допомогою номерів, починаючи з нуля. Наприклад, у командному рядку
cat text_1 text_2...text_9
інтерпретатор розбиває рядок, і аргументи ідентифікуються пара-метрами $1...$9. Для імені команди завжди використовується $0. Отже, $0 – це cat, $1 – це text_1, $2 – це text_2 і т.д. Для присвоювання значень позиційним змінним використовується команда set, наприклад:
set arg_1 arg_2... arg_9
Тут $1 присвоюється значення першого аргументу arg_1, $2 – arg_2 і т.д. Для доступу до аргументів використовується команда echo, наприклад:
echo $l $2 $9
arg_1 arg_2 arg_9
Для одержання інформації про всі аргументи (включаючи останній) використовують метасимвол “*”. Наприклад:
echo $*
arg_2 arg_3... arg_10 arg_11 arg_12
За допомогою позиційних змінних shell вдається зберегти ім’я команди за допомогою $0 та її аргументи (за допомогою $1 $2). Для виконання команди інтерпретатор shell повинен передати їй аргументи; їхній порядок може регулюватися за допомогою позиційних змінних.
Спеціальні змінні. Змінні – ? # $ ! встановлюються тільки shell. Вони дозволяють за допомогою команди echo отримати наступну інформацію:
“-“ – поточні прапорці інтерпретатора (установка прапорців може бути змінена командою set);
“#” – число аргументів, що повинне бути збережене інтерпретатором при виконанні якої-небудь команди;
“?” – код повернення останньої виконуваної команди;
“$” – числовий ідентифікатор поточного процесу PID;
“!” – PID останнього фонового процесу.
Екранування. Розглянемо більш докладно прийоми екранування, використовувані в shell. Як засоби екранування використовуються подвійні лапки (“ ”), одинарні лапки (‘ ’) і обернений слеш (\).
Можна в одному рядку записувати декілька приcвоювань.
x=22 y=33 z=$x
A= “$x” B= ‘$x’ C=\$x
D= “$x + $y + $z” E= ‘$x + $y + $z’ F=$x\ +\ $y\ +\ $z
(присвоювання G=$x + $y не було б виконане через пробіли). Тоді:
echo A = $A B = $B C = $C
echo D = $D E = $E F = $F
eval echo evaluated A = $A
eval echo evaluated B = $B
eval echo evaluated C = $C
видадуть на екран
A = 22 B = $x C = $x
D = 22 + 33 + 22 E = $x + $y + $z F = 22 + 33 + 22
evaluated A = 22
evaluated B = 22
evaluated C = 22
У трьох останніх випадках використана своєрідна команда “eval” (від evaluate – визначати), що у підставленій у неї (як аргумент) команді виконує визначення змінних (якщо такі є). У результаті значення “A” залишається попереднім, оскільки “A” має значення “22”. А змінні “B” і “C” мають значення “$x”. За рахунок визначення, що було виконано командою “eval” – evaluated “B” і “C” дають значення “22”.
Ще один приклад на “eval”. Нехай
w=\$v v=\$u u=5
У результаті виконання команд
echo $w
eval echo $w
eval eval echo $w
на екран буде виведено
$v
$u
5
Наведемо ще приклади, пов’язані з екрануванням переведення рядка. Нехай змінній “string” присвоєне значення “масиву” 2×3:
abc
def
Звернемо увагу, що для запобігання присвоювання зайвих пробілів другий рядок масиву початий з першої позиції наступного рядка:
string= “abc
def”
Тоді три варіанти запису змінної в команді “echo”
echo $string
echo ‘$string’
echo “$string”
дадуть відповідно три різних результати:
abc def
$string
abc
def
а послідовність команд
echo “рядок перший
рядок другий” > f1
echo ‘рядок перший
рядок другий’ > f2
cat f1 f2
видасть послідовно однакові файли f1 і f2:
рядок перша
рядок друга
рядок перша
рядок друга
Зауважимо також, що бэк-слэш (\) не тільки екранує наступний за ним символ, що дозволяє використовувати спеціальні символи просто як символи, що представляють самі себе (він може екранувати й сам себе – \\), але в командному файлі бэк-слэш дозволяє об'єднувати рядки в один (екранувати кінець рядка).
Приклад командного рядка, що наводився раніше:
cat f1 | grep -h result | sort | cat -b > f2
може бути записаний у командному файлі, скажімо, як
cat f1 | grep -h \
result | sort | cat -b > f2
Експорт змінних. В ОС Linux існує поняття процесу. Процес виникає тоді, коли запускається на виконання яка-небудь команда (розрахунок).
Наприклад, при наборі на клавіатурі “р <Enter>” породжується процес розрахунку “р”. У свою чергу “р” може породити інші процеси. Припустимо, що “р” викликає розрахунки “р1” і “р2”, які послідовно породжують відповідні процеси.
У кожного процесу є своє середовище – безліч доступних йому змінних. Наприклад, до запуску розрахунку “р” уже існувало середовище, у якому уже були визначені деякі змінні (про стандартні змінні мова йтиме трохи пізніше). Запуск “р” породжує нове середовище; уже в ньому будуть породжені розрахунки “р1” і “р2”.
Змінні локальні в рамках процесу, у якому вони оголошені, тобто де їм привласнені значення (опис змінних відсутній – вони усі одного типу). Для того, щоб вони були доступні й іншим процесам, треба передати їх явно. Для цього використовується вбудована команда “export”.
Приклад
Нехай розрахунок (командний файл) “p”, що має вигляд:
# розрахунок p
echo Розрахунок p
var=0 var=1
echo var=$var var=$var
export var
p1 # виклик розрахунку p1
p2 # виклик розрахунку p2
echo Знову розрахунок p: var=$var var=$var
викликає командні файли “p1” і “p2”, що мають вид:
# розрахунок p1
echo Розрахунок p1
echo var=$var var=$var
var=a var=b
echo var=$var var=$var
export var
# розрахунок p2
echo Розрахунок p2
echo var=$var var=$var
var=A var=B
echo var=$var var=$var
export var
На екран буде видана наступна інформація:
Розрахунок p
var=0 var=1
Розрахунок p1
var= var=1
var=a var=b
Розрахунок p2
var= var=1
var=A var=B
Знову розрахунок p: var=0 var=1
Із прикладу видно, що значення змінних експортуються тільки у викликувані розрахунки (і не передаються “нагору” і “убік”). Експортувати змінні можна й командою “set” із прапором “-a”.
Використання оператора if. Shell дозволяє структурувати умовні
переходи з допомогою оператора if. Найпростіша форма оператора if наступна:
if список команд
then список команд
fi
Список команд, що стоїть після if, виконується і, якщо код завершення останньої виконаної команди рівний 0, то виконується список команд, означений після then. Слово fi значить кінець команди if.
Щоб виконати альтернативний набір команд при ненульовому коді завершення, використовується умова else, що записується наступним чином:
if список команд
then список команд
else список команд
fi
Наприклад (файл повинен мати ім’я *.sh) :
if test -f “$1”
# чи є $1 файлом?
then pr $1
elif test -d “$1”
# якщо немає, то чи є $1 каталогом?
then (cd $1; pr *)
else echo $1 не є ані файлом, ані каталогом
fi
Наведений приклад виконується наступним чином: якщо значення першого позиційного параметра є ім’ям файла (-f), то цей файл друкується; якщо ні, то перевіряється, чи є це ім’я ім’ям каталогу (-d). Якщо це так, то ви переходите в цей каталог (cd) і друкуєте всі файли, що знаходяться в ньому (pr *). В усіх інших випадках з’являється повідомлення про помилку.
Команди if можуть вкладатися одна в одну, але кожний if обов’язково повинен мати свій fi.
Використання оператора case. Оператор case також дає можливість перевіряти різноманітні умови. Основний формат оператора case наступний:
case підрядок in
Шаблон ) список команд ;;
....
Шаблон ) список команд ;;
esac
Shell намагається знайти означений підрядок по черзі в кожному шаблоні, використовуючи ті самі угоди, що і при генерації імен файлів. Якщо відповідність встановлена, то виконується список команд після цього шаблону. Два символи крапки з комою (;;) є позначкою кінця оператора case і необхідні після кожного шаблона, окрім останнього. Зверніть увагу на те, що тільки одне значення шаблона (з означених) може виявитися в підрядку, порівняння з шаблонами виконується послідовно, і тому якщо першим шаблоном виступає зірочка (*), всі інші значення ігноруються.
З одним і тим самим списком команд може бути зв’язано декілька альтернативних шаблонів, розділених символом (|).
case $i in
*.c) cc $i
;;
*.h | *.sh)
: do nothing
;;
*) echo “$i of unknown type”
;;
esac
У цьому прикладі для другого набору шаблонів не виконується жодних дій, оскільки вказана порожня команда (:). Зірочка використовується як шаблон, відповідний будь-якому слову.
Код завершення оператора case рівний коду завершення останньої виконаної команди. Якщо жодні команди не виконувалися, то код завершення рівний 0.
Умовні цикли: while і until. Основна форма команди while має вигляд:
while список команд
do
список команд
done
Спочатку виконуються команди з першого списку, і якщо код завершення останньої команди в цьому списку рівний 0, тоді виконуються команди з другого списку. Ця послідовність повторюється до тих пір, доки код завершення першого списку рівний 0. Щоб цикл виконувався до тих пір, доки код завершення першого списку не рівний 0, треба замінити while на until.
Будь-який рядок може бути замінений символом “крапка з комою”. Код завершення команд while і until рівний коду завершення останньої виконаної команди в другому списку. Якщо команди з другого списку не виконувалися, код завершення рівний 0.
Організація циклу для списку: for. Часто буває потрібно виконати деякий набір операцій для кожного файла з якого-небудь списку або виконати одну команду для кожного з декількох аргументів. Для цього існує команда for.
Формат команди for наступний:
for змінна in список значень
do
cписок команд
done
Значення змінних в списку розділяються пропусками. Команди в списку команд виконуються один раз для кожного значення змінної з списку значень. Змінній по черзі присвоюється кожне значення з списку. Наприклад, наступний цикл for виробляє порівняння вхідних текстів xec.c, cmd.c і word.c у поточному каталозі з файлами з такими самими іменами, але в каталозі /usr/src/cmd/sh:
for CFILE in xec cmd word
do diff $CFILE.c /usr/src/cmd/sh/$CFILE.c
done
Зверніть увагу на те, що перше згадування імені CFILE відразу після слова for не супроводжується появою символу “$”, оскільки в даному випадку використовується ім’я змінної, але не її значення.
Слово “in”, що є частиною команди for, можна не вказувати. В цьому випадку поточний набір позиційних параметрів буде використаний замість списку значень. Це корисно в тому випадку, якщо набір команд виконується для кожного аргументу з списку аргументів, загальне число яких невідомо.
Як приклад створіть файл з ім’ям echo2, що містить наступний текст:
for word
do echo $word$word
done
Змінити статус файла echo2:
chmod +x echo2
Тепер введіть наступну команду:
echo2 ma pa bo fi yo no so ta
Результатом виконання цієї команди буде:
mama papa
bobo fifi
yoyo nono
soso tata
Управління циклами: break і continue. Для припинення виконання циклів while або for застосовується команда break. Команда continue негайно запускає виконання наступного кроку в циклі. Ці команди діють тільки якщо вони зустрічаються між командами do і done.
Команда break завершує виконання тільки в даний момент циклу ,що виконується, викликаючи продовження роботи команд, що стоять після найближчого done. Вихід з n-рівневого вкладеного циклу досягається командою break n.
Команда continue продовжує виконання з найближчого відкритого оператора for, while або until, тобто того, що містить цей оператор continue. Ви також можете задати аргумент n в команді continue, і тоді виконання буде продовжене з n-го вкладеного циклу:
# Ця процедура інтерактивна.
# Команди “break” і “continue” використовуються
# користувачем для управління вводом даних.
while true #loop forever
do echo “Please enter data”
read response
case “$response” in
“done”) break
# no more data
;;
“”) # just a carriage return,
# keep on going
continue
;;
*) # process the data here
;;
esac
done
Кінець файла і вихід. Коли Shell виявляє кінець файла в процедурі, вона завершується, вертаючи в свій батьківський процес код завершення останньої команди, виконаної до відкриття кінця фай-ла. Вихід з Shell самого високого рівня виробляється натиском клавіші [Ctrl + d] (при цьому користувач вивантажується з системи).
Команда exit моделює кінець файла, встановлюючи код завершення рівним значенню свого аргументу, якщо він є. Так, процедуру можна нормально завершити, вказавши в кінці файла “exit 0”.
Команда echo. Команда echo має наступний синтаксис:
echo [опції] [аргументи]
echo копіює свої аргументи в стандартний вивід, після кожного окрім останнього аргументу додається пропуск. Після останнього виведеного аргументу звичайно ставиться символ нового рядка. Ви можете використати цю команду для видачі запрошення для вводу, виводу повідомлень в процедурах Shell або для додавання декількох рядків у вихідний потік в середині конвеєра. Інше застосування echo – це перевірка процесу генерації списку аргументів для інших команд.
Ви можете замість команди ls використати echo, оскільки остання працює значно швидше.
Опція -n вказує echo не ставити символ нового рядка в кінці виведеного рядка. Так, наступні дві команди створюють запрошення для вводу і після цього дадуть можливість вводити інформацію на той самий рядок де знаходиться запрошення:
echo -n ‘enter name:’
read name
Оцінка арифметичних виразів: expr. Команда expr здійснює арифметичні і логічні дії над цілими числами. Як її аргументи можна використати шаблони. Ця команда оцінює окремі вирази і записує результат в стандартний вивід. expr можна використати всередині зворотних лапок для встановлення значення змінних. Нижче наводяться характерні приклади використання цієї команди:
# збільшити $A
A='expr $A + 1'
# помістити символи $1 з 3-го по останній
# в підстроку substring
substring= ‘expr “$1”: ‘..\(.*\)”
# отримати довжину $1
c= ‘expr “$1”:’.*”
Найбільш часто expr застосовується для підрахунку числа ітерацій в циклах.
Команди true і false вертають код завершення 0 або не 0, відповідно. Їх часто використовують для створення безумовних циклів, наприклад:
while true
do echo forever
done
У результаті слово forever буде з’являтися на екрані до тих пір, доки не буде натиснуто INTERRUPT.
Приклади процедур Shell (всі тексти програм повинні знаходитись в файлах з розширенням .sh)
COPYTO
# Формат: copyto dir file …
# копіює перераховані файли в каталог dir
# при умові, що вказано не менше двох
# аргументів, що ‘dir’ є каталогом,
# і що кожний наступний елемент
# являє собою файл, доступний для читання.
if test $# -lt 2
then echo “$0: usage: copyto directory file …”>&2
elif test ! –d $1
then echo “$0: $1 is not a directory”;>&2
else dir=$1; shift
for eachfile
do cp $eachfile $dir
done
fi
Ця процедура використовує команду if для виводу повідом-лень про неправильне використання процедури. Цикл for в кінці процедури продивляється всі аргументи, крім першого.
FSPLIT
# Формат: fsplit file1 file2
# Читання стандартного виводу і розбиття його на
# 3 частини з додаванням строки, що містить не менше
# однієї літери до файла file1, додавання іншої строки
# з цифрами, але без букв до файла file2, та
# зброшенням іншого
count=0 gone=0
while read next
do
count=“’expr $count +1’”
case “$next” >> $1 ;;
*[A-Za-z]*)
echo “$next” >> $1 ;;
*[0-9]*)
echo “$next” >> $2 ;;
*)
gone=“’expr $gone +1’”
exac
done
echo “$count lines read, $gone thrown away”
На кожній ітерації циклу з вхідного потоку зчитується рядок і аналізується. Цикл закінчується лише тоді, коли команда read знайде кінець файла. Зверніть увагу на використання команди expr.
MKFILES
# Формат: mkfiles pref [quantity]
# Створює файли “quantity”.
# За замовчуванням – 5, як показана на наступному рядку
quantity=${2-5}
i=1
while test “$i” –le “quantity”
do
> $1$i
i=“‘expr $i +1’”
done
Процедура mkfiles використовує переадресацію виводу для створення файлів нульової довжини. Команда expr використовується для підрахунку числа ітерацій в циклі while.
NULL
# Формат: null files
# Створює кожний з вказаних файлів як порожній
for eachfile
do
>$eachfile
done
Процедура використовує той факт, що в результаті переад-ресації виводу, якщо результуючого файла з таким ім’ям немає, ство-рюється порожній файл.
WRITEMAIL
# Формат: writemail message user
# Якщо користувач зареєструвався,
# повідомлення виводиться на термінал;
# в протилежному випадку, посилається користувачеві.
echo “$1” | {write “$2” || mail “$2” ; }
Ілюстрація використання командного групування. Повідом-лення, визначене як “$1”, передається команді write, і, у випадку не-вдалого завершення останньої, команді mail.