С чего начинается программирование...

читать лучше с начала!

На сайті розглядаються основи роботи з мультимедійною інформацією на персональному комп'ютері. Описано ряд програм для закису, обробки й відтворення звуку й зображення.

Представлено деякі Wіndows-програми комунікацій реального часу ( ІP-Телефонії).

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

Серед наших користувачів, як правило, користувачі комп'ютера в дома й в офіса, так і на починаючих розроблювачів програмного забезпечення - ми даємо основи програмування в середовищі Borland C++ Buіlder. Наша аудиторія - це, перш за все, школярі старших класів, студенти і широке коло людей, що просто використовують комп'ютер вдома й на роботі.

* ГЛАВА 10. Змішані прийоми *



      Введення
      Способи перетворення в мові shell
      conv
      Модулі перетворення
      dtoh
      dtoo
      htod
      htoo
      Тонкості bc
      otod
      otoh
      Прийоми мови shell для забезпечення гнучкості програм
      Хитрості мови shell
      Читайте уведення із клавіатури, поки перебуваєте в циклі,
      приєднаному до програмному каналу
      Запуск дочірньої мови shell
      Рівні мови shell і уведення-висновок
      Убудоване уведення
      З редактором ed
      З файлом a.out
      C архівами мови shell
      Керування статусом циклу
      Фільтри й синтаксис
      Недоліки/особливості програмування мовою shell
      Програма для перенапрямку помилки
      Некоректний код повернення
      Хитрості редактора Vi
      Повернення в мову shell
      Підтримка Escape
      Макроси
      Команда "One-Liners" - малюсінька, але потужна .
      - 2

      Введення

      Ця книга є підсумком багаторічної роботи з підбора й розвитку інструментальних засобів ОС UNIX. Багато речей, які не хотілося б залишати без уваги, не вписали в контекст попередніх глав. Це й закінчені процедури, подібні представленим раніше, і невеликі, але дуже потужні фрагменти програм. Крім того, висловлено деякі корисні ідеї й представлені методи обробки загальних ситуацій мовою shell.

      Способи перетворення

      Оскільки комп'ютери і їхні скільки-небудь утиліти використовують при роботі різні системи числення, часто виникає необхідність перетворення підстав систем числення. Ці перетворення забезпечуються добре знайомими фахівцям командами UNIX bc (калькулятор довільної точності) і dc (яка приблизно розшифровується як настільний калькулятор ("desk calculator")). Більшість із існуючих можливостей або носять дуже обмежений характер, або їх важко використовувати в ряді ситуацій, тому буде розглянуте питання як використовувати існуючі можливості UNIX, щоб будь-яке перетворення було як можна більше легко здійсненним.

Назва: conv

conv Переводить числа з однієї системи числення в іншу
Призначення: Забезпечує можливість перетворення підстави системи
      числення
Виклик conv
Приклад виклику:
      $conv Викликати головне меню різних перетворень

      2 Вибрати опцію 2 ( із шестнадцатиричной у десяткову)

      FFF Увести шестнадцатиричное число FFF. На виході програми
      одержимо десятковий еквівалент


      Вихідний текст для функції conv
1 : 2 # @(#) conv v1.0 Перетворення підстави системи
      числення, використовуючи shell Автор: Russ Sage 3 4 while : 5 do 6 echo " 7 8 Перетворення підстав 9 -і-і-і-і-і-і-і-і-і-і-і-і 10 1 - Десяткове в шестнадцатиричное 11 2 - Шестнадцатиричное в десяткове 12 3 - Десяткове у восьмеричне 13 4 - Восьмеричне в десяткове 14 5 - Восьмеричне в шестнадцатиричное 15 6 - Шестнадцатиричное у восьмеричне 16 17 enter choice (1-6, <>): \c" 18 read CHOICE 19 20 case $CHOICE in 21 "") exit;; 22 1) echo "\пвведите десяткове число (<> to exit): \c" 23 read DEC 24 if [ "$DEC" = ""] 25 then exit 26 fi 27 HEX='. dtoh' 28 echo "\n${DEC}d = ${HEX}x";; 29 2) echo"\nвведите шестнадцатиричное число
      у верхньому регістрі (<> to exit): \c" 30 read HEX 31 if [ "$HEX" = ""] 32 then exit 33 fi 34 DEC='. htod' 35 echo "\n${HEX}x= ${DEC}d;; 36 3) echo "\nвведите десяткове число в
      верхньому регістрі (<> to exit): \c" 37 read DEC 38 if [ "$DEC" = ""] 39 then exit 40 fi 41 OCT='. dtoo' 42 echo "\n${DEC}d = ${OCT}o";; 43 4) echo "\nвведите восьмеричне число
      (<> to exit): \c" 44 read OCT 45 if [ "$OCT" = ""] 46 then exit 47 fi 48 OCT='. otod' 49 echo "\n${OCT}o = ${DEC}d";; 50 5) echo "\nвведите восьмеричне число
      (<> to exit): \c" 51 read OCT 52 if [ "$OCT" = ""] 53 then exit 54 fi 55 HEX='. otoh' 56 echo "\n${OCT}o = ${HEX}x";; 57 6) echo "\nвведите шестнадцатиричное число
      у верхньому регістрі (<> to exit): \c" 58 read НЕХ 59 if [ "$НЕХ" = ""] 60 then exit 61 fi 62 OCT='. htoo' 63 echo "\n${HEX}x = ${OCT}o";; 64 *) echo "\n$ CHOICE-Невідома команда";; 65 esac 66 done

      Змінні оточення
CHOICE - Вибір команд із головного меню DEC - Видає десяткове значення як результат
      перетворення HEX - Видає шестнадцатиричное значення як

      - 4
      результат перетворення OCT - Видає восьмеричне значення як
      результат перетворення

      Опис

      Навіщо нам потрібна функція conv ?

      Виконання числових операцій великого обсягу в командних файлах мови shell - це далеко не сама гарна ідея. Командні файли являются досить повільними самі по собі, а виконання математичних операцій ще більше сповільнює їхню роботу. Однак, процедури мови shell мають математичні можливості, і Ви, можливо, захочете ними скористатися. Якщо Вам потрібно перетворити кілька чисел у процессе написання програми, то для цієї мети досить зручно викликати процедуру мови shell. Оскільки conv - це програма, керована меню, Вам не прийде турбуватися про запам'ятовування складного синтаксису, котрый використовують деякі системні утиліти перетворення.

      Що робить conv?

      Цей інструментальний засіб забезпечує можливість перекладу чисел з однієї системи числення в іншу. Можна переводити десяткові, шестнадцатиричные й восьмеричні дані. Число, записане в одній із цих форм, може бути переведене в кожну з двох форм, що залишилися.
      Режим роботи програми вибирається з головного меню. У меню є шість пунктів. Після того як Ви вибираєте число між 1 і 6, програма просить Вас увести число яке Ви хочете перетворити. Відбувається перетворення й на виході програми Ви одержуєте два значення - число, що Ви перетворюєте й число, до якого воно було перетворено. Перетворення здійснюються шляхом виклику зовнішніх процедур, про які буде йти мова далі в цій главі, так що перед запуском conv необхідно переконатися, що Ви включили їх в вашу систему й розмістили в тім же каталозі, що й conv.
      Якщо Ви введете команду, що не ввійшла у вищезгаданий перелік, те буде видане повідомлення про помилку й знову буде виведене головне меню.

      Пояснення

      Рядка 4-66 - це один великий нескінченний цикл while. Ми використовуємо нескінченний цикл, щоб у випадку помилкового уведення програма повернулася в головне меню для повторного уведення. Для того, щоб вийти із програми, потрібно перервати цикл, тобто вийти із циклу.
      Рядка 6-17 друкують меню й видають підказку для вибору. Якщо Ви просто натиснете "Уведення", програма завершить свою роботу.
      Рядок 18 читає уведення із клавіатури, і рядка 20-65 виконують вибір за умовою для цієї величини. Якщо отримано нульовий (порожній) уведення, то програма завершує свою роботу.
      Рядка 22-28 здійснюють переклад чисел з десяткової в шестнадцатиричную системи числення. Оскільки всі модулі перекладу відповідають тому самому зразку, те детально ми розглянемо тільки даний модуль.
      Підказка запитує число в рядку 23. У рядках 24-26 перевіряється, чи не було уведене значення порожнім. Рядок 27 виглядає трохи загадково, викликаючи один із зовнішніх командних файлів dtoh для перетворення десяткових чисел у шестнадцатииричные. Звернете увага на те як одна програма виконує іншу.
      Командний файл dtoh запускається, використовуючи команду ".". Це означає : "Виконаєте програму, використовуючи той же shell". Процедура dtoh використовує змінну DEC для уведення числа й видає

      - 5 перетворене число на стандартний висновок. Щоб записати це число у змінну, ми робимо присвоєння, потім запускаємо програму, використовуючи командну підстановку. Рядок 28 видає на екран первісне десяткове число й шестнадцатиричное, до якого воно було перетворено.
      Варіанти 2, 3, 4, 5 і 6 працюють аналогічно. Єдине, що міняється - це ім'я змінної, котре відповідає типу перетворення й назва командного файлу (скрипта), що викликається для цього перетворення.


      Модулі перетворення

      Тепер давайте розглянемо окремо кожний з модулів перекладу. Ці модулі або командні файли мови shell використовують команду UNIX bc, щоб здійснювати перетворення підстав систем числення. Не можна сказати, що команда bc - це найбільш простий і зручний спосіб перекладу, але проте вона працює, і єдине, що нам потрібно, - це вивчити її й помістити в командний файл.

Назва : dtoh

dtoh Десяткові в шестнадцатиричные.
Призначення: Перетворює вхідні десяткові числа у вихідні
      шестнадцатиричные числа.
Синтаксис: $DEC="decimal_number"; HEX='.dtoh'
Приклад виклику

      $DEC="25";HEX='.dtoh'
      $echo $HEX
Привласнити DEC початкове значення 25, викликати dtoh для його перетворення й записати результат в HEX. Вивести результати на екран.


      Вихідний текст для dtoh
1 : 2 # @(#) dtoh v1.0 Перетворення мови shell--десяткові в
      шестнадцатиричные Автор: Russ Sage 3 4 bc <

      Опис

      Навіщо нам потрібний dtoh ?

      Ця процедура перетворює десяткове число в шестнадцатиричное - простий варіант перетворення, що нам може знадобитися.

      Що робить dtoh?


      - 6
      Dtoh виконує перетворення десяткових у шестнадцатиричные, використовуючи існуюче базове перетворення, що UNIX забезпечує за допомогою команди bc. Маніпулюючи уведенням і висновком команди bc, ми можемо використовувати її можливості перетворення.

      Пояснення

      Технологія, по якій все це відбувається, досить проста. Метод виконання - використовуючи команду мови shell ".". Це означає использовать той же shell для запуску команди, а не дочірній. Коли команда виконується цією же мовою shell, всі змінні, які в даний момент мають якісь значення, доступні для командного файлу dtoh. Ми використовуємо цю перевагу й припускаємо для dtoh, що Ви правільно встановили змінної мови shell.
      Рядок 4 викликає команду bc, що представляє із себе калькулятор самого нижнього рівня. За замовчуванням bc використовує десяткове уведення й висновок. Ми встановлюємо підставу виходу в 16 в рядку 5. Це означає, що будь-яке число, що ми друкуємо із цього моменту, друкується як шестнадцатиричное число.
      Рядок 6 уводить десяткове число для bc, розширюючи його значення як уведення для bс. Bc видає на екран число, записане в шестнадцатиричной системі числення. Ми перетворили число.
      Єдине, що залишилося зробити - це помістити результат в змінної мови shell у зухвалій програмі. Але це вже зроблено в зухвалій програмі завдяки способу виклику процедури. Преобразование відбувається усередині bc.

      Дослідження

      Зухвалий синтаксис - це не єдиний спосіб використовувати ті ж самі програми. Це простіше всього, але існують і інші способи.
      У наведеній нижче програмі, використовується інший метод виклику. Замість командної підстановки тут використовується дочірній shell, стандартний висновок якого перенаправляється. Зверніть увагу, що результат записується у файл, а не в змінної мови shell. Запис у файл може виявитися корисної, якщо ті ж самі дані знадобляться іншим програмам або якщо Ви хочете їх використовувати після закінчення роботи програми.

      $ DEC="150"; (. .dtoh) > HEX
      $ echo "шестнадцатиричное число: 'cat HEX'"

      Позначення () запускає викликувану процедуру в дочірньому мові shell. Використовуючи "." для її виконання, ми по колишньому маємо доступ до змінного DEC. Стандартний висновок перенаправляється в HEX. Луна супровід одержує значення, використовуючи командну підстановку. Результат cat міститься в луну пропозиція.

Назва: dtoo

dtoo Десяткові у восьмеричні
Призначення Переводить вхідні десяткові числа у вихідні
      восьмеричні.
Синтаксис: DEC="decimal_number"; OCT='.dtoo'
Приклад виклику

      $DEC="16";OCT='.dtoo'

      - 7
      $echo $OCT
Привласнити DEC початкове значення 16, викликати dtoo для її перетворення й записати результат в OCT. Вивести результати на екран.


      Вихідний текст для dtoo
1 : 2 # @(#) dtoo v1.0 Перетворення мови shell--десяткові в
      восьмеричні Автор: Russ Sage
      bc <      obase = 8
      $DEC
      !

      Опис

      Оскільки це й наступні засоби реобразования працюють аналогічно dtoh, крім представляється специфики, що, перетворення, ми опускаємо детальні пояснення.

Назва: htod

htod Шестнадцатиричные в десяткові
Призначення Переводить вхідні шестнадцатиричные числа у вихідні
      десяткові.
Синтаксис: HEX="hex_number"; DEC='.htod'
Приклад виклику

      $HEX="1EAC" ; DEC='.htod'
      $echo $DEC
Привласнити HEX шестнадцатиричное значення, перетворити його, надрукувати результати.


      Вихідний текст для htod
1 : 2 # @(#) dtoo v1.0 Перетворення мови shell--шестнадцатиричные
      у десяткові Автор: Russ Sage
      bc <      ibase = 16
      $HEX
      !

Назва: htoo

htoo Шестнадцатиричные у восьмеричні
Призначення Переводить вхідні шестнадцатиричные числа у вихідні
      восмеричные.
Синтаксис: HEX="hex_number"; OCT ='.htoo'

      - 8
Приклад виклику

      $HEX="F1E" ;
      $OCT='.htoo'
      $echo $OCT

      Привласнити HEX шестнадцатиричное значення, перетворити його, надрукувати восьмеричне число.


      Вихідний текст для htoo
1 : 2 # @(#) htoo v1.0 Перетворення за допомогою мови shell -і
      шестнадцатиричные у восьмеричні Автор: Russ Sage
      bc <      ibase = 16
      obase = 8
      $HEX
      !


      Тонкості bc

      Один з важливих моментів - це порядок, у якому ми змінювали підстави. Спочатку - більша підстава, потім менше. Після того як ми змінюємо ibase на 16, всі вхідні числа розглядаються як шестнадцатиричные. Так що рядок 6 не має нового подання: ми установлюємо obase рівним 8, а число 8 має одне й теж значення в шестнадцатиричной і десяткової системах.
      Що б відбулося, якби ми дорівняли obase до 10 ? Число 10 було би інтерпретовано в шестнадцатиричном змісті, а шестнадцатиричное 10 - це 16. Нам би довелося записати obase у шестнадцатиричной системі (підстава 16, оскільки 10х вхідне = 16d вихідне). Вам прийде відслідковувати подібні речі.

Назва: otod

otod Восьмеричні в десяткові
Призначення: Переводить вхідні восьмеричні числа у вихідні
      десяткові.
Синтаксис: OCT="octal_number"; DEC = '.otod'
Приклад виклику

      $OCT="777" ;
      $DEC='.ot
      $echo $DECod'
Привласнити OCT восьмеричне число, перетворити його в десяткове, надрукувати результат.


      Вихідний текст для otod
1 : 2 # @(#) otod v1.0 Перетворення мови shell--восьмеричні в
      десяткові Автор: Russ Sage

      - 9
      bc <      ibase = 8
      $OCT
      !

Назва: otoh

otoh Восьмеричні в шестнадцатиричные
Призначення: Переводить вхідні восьмеричні числа у вихідні
      шестнадцатиричные.
Синтаксис: OCT="octal_number"; HEX = '.otoh'
Приклад виклику

      $OCT="777" ;
      $DEC='.otoh'
      $echo $HEX

      Привласнити OCT восьмеричне число, перетворити значення OCT в шестнадцатиричное, запускаючи otoh. Привласнити результат перетворення HEX, відобразити значення HEX.


      Вихідний текст для otoh
1 : 2 # @(#) otoh v1.0 Перетворення за допомогою мови shell -і
      восьмеричні в шестнадцатиричные
      Автор: Russ Sage
      bc <      obase = 16
      ibase = 8
      $OCT
      !


      Хитрості мови shell

      Кожна мова програмування має свої власні синтаксичні "підводні камені". Потрібні роки, щоб розібратися в всіх тонкостях і, здається, що вивчити їх все просто неможливо. Shell у цьому плані нічим не відрізняється від інших мов.
      У цьому розділі ми розглянемо деякі моменти, про які Вам потрібно знати, якщо серйозно програмувати мовою shell. Це дуже вузькі області, але вони можуть стати серйозною перешкодою, якщо Ви зштовхнетеся з ними при написанні програм.


      Читайте уведення із клавіатури, поки перебуваєте в циклі,
      приєднаному до програмному каналу

      Команда читання мови shell читає дані зі стандартного уведення. У ранніх версіях мови shell (змінено недавно тільки в System V), Ви не мали можливості перенаправляти уведення для команди читання.
      Питання в тім, як читати із клавіатури, поки стандартне уведення приєднаний до кінця програмного каналу? Рішення питання - це брати уведення безпосередньо із клавіатури. UNIX забезпечує це через пристрій /dev/tty. Розглянемо наступний приклад:


      - 10 who | awk '{ print $1 }' | while read NAME do
      echo "mail to $NAME: \c"
      KB = 'Line < /dev/tty'
      if [ "$KB" = "y"]
      then mail $NAME
      fi done
Ця програма відображає на екрані список що зареєструвалися користувачів і запитує Вас, чи не хочете Ви послати повідомлення по пошті кому-небудь із користувачів. Якщо Ви відповідаєте "Y", команда пошти запускається, причому їй на вхід передається ім'я користувача, якого Ви вибрали.
      Висновок програми awk переспрямований на стандартне уведення циклу while. Команда читання читає з stdin, що є списком імен користувачів, отриманим з вихідного потоку команди who. Вам видається підказка відправити повідомлення до конкретної людини, потім Ви переходите до команди read. Ми збираємося використовувати команду Line (1). Вона читає по одному рядку з даного пристрою. Ми викликаємо команду line і перенаправляємо її стандартне уведення на спеціальне пристрій /dev/tty. Тепер уведення йде із клавіатури в той час як цикл усе ще читає свій stdin із програмного каналу.
      Змінна KB одержує значення, що рівняється з "y". Якщо змінна має значення "y", те викликається команда mail, що в якості параметра одержує ім'я користувача, записана в даний момент у змінної NAME.


      Запуск дочірньої мови shell

      Shell - дуже багатобічна програма. Вона може працювати в інтерактивному, фоновому й командному режимах. Її уведення може бути переспрямовано, підключений до програмного каналу, він може бути з убудованого тексту або з вихідного потоку приєднаної команди.
      Ми хочемо звернути Вашу увагу на гнучкість мови shell на уровнях його виконання. Shell може породжувати інші мови shell для виполнения частин його роботи. До якої глибини він може опуститися? Зчи міняють працюючі дочірні мови shell виконання й результат доманд, запущених з мов shell першого рівня? На це важко ответить. Усе, що ми можемо - це випробувати деякі речі й подивитися чи представляє інтерес те, що ми вивчили чи ні. Shell може підлогичать своє уведення зі стандартного уведення, що є або уведенням з клавіатури, або з файлу, або із програмного каналу. Цю гнучкість мови shell ми можемо використовувати в нашу користь. Синтаксис виглядає наступної бразом:

      echo $@ | sh
Ми відображаємо аргументи в командному рядку й посилаємо її в програмний канал. Shell наприкінці програмного каналу читає текст командного рядка з stdin (певного -) і виконує команди. Цей метод також ілюструється в главі 9 у команді umntsys.

      Якщо ми можемо перенаправляти стандартне уведення команди, ми можемо також використовувати можливість уведення мови shell "документ тут". Використовуючи позначення <<, ми можемо обмежити область тексту й направити його в стандартний канал уведення командного файлу.
      Щоб продемонструвати цикл аналогічний попередній, використовуючи тільки убудований текст, розглянемо наступний приклад:

      sh << !
      $@
      !

      - 11

      Ця програма викликає shell і змушує стандартне уведення для мови shell іти з тексту, обмеженого символами !. Ми передаємо усе з командного рядка, так що це буде аналогічно тому, як якщо би ми друкували команди для мови shell першого рівня.


      Рівні мови shell і уведення-висновок

      Іншою цікавою й загадковою областю є уведення й висновок з мов shell, що працюють на різних рівнях. Один із прикладів пов'язаний з спробою захопити процес номер id, коли ви поміщаєте завдання id в фоновий режим, використовуючи символ & з командного рядка. Якщо Ви використовуєте цю форму, Ви одержите такий результат:

      $ ls &
      1034
      $ file1
      file2
      file3
де file1, file2 і file3 - висновок команди ls. Усе, що ми хочемо зробити - це помістити процес номер id (у цьому випадку 1034) в змінну, доступ до якої ми одержимо пізніше. Один цікавий момент тут - якщо Ви робите ту ж саму команду усередині командного файлу, номер процесу id не друкується.
      Для того, щоб насправді захопити процес із номером id, потрібно виявити спритність. Необхідно небагато поэкспериментировать, щоб знайти робочу комбінацію:

      $(ls &) 2 > idfile

      Команда ls запускається як дочірній shell, використовуючи позначення (). Дочірній shell міститься у фоновий режим, використовуючи символ & . Коли результат процесу id відображений, він направляється у файл помилок дочірньої мови shell, що його виконує. Ми просто перенаправляїм стандартну помилку у файл і одержуємо число! Тепер ми можемо сделать що-небудь типу:

      $ kill -9 'cat idfile'
де процес id, переданий kill, генерується з команди cat, що друкує процес id, захоплений раніше. Це може дати програмам опцію "kill self", де вони можуть відслідковувати їх id, щоб вам не довелося це робити. Програма watch, що ми бачили в главі 6 робить щось подібне.


      Убудоване уведення

      Редактор vi зручний доти, поки Вам не потрібно робити порядкове редагування тексту або редагування в командному режимі. Sed теж непоганий редактор, але в ньому не передбачена можливість переміщення по файлі. Sed може переміщатися тільки уперед по файлі до кінця файлу. Всі наші проблеми може вирішити скромний редактор ed.


      З редактором ed

      Еd є інтерактивним редактором і в ньому є всі необхідне для обробки виражень. Оскільки він читає стандартний уведення для своїх команд, ми можемо поміщати в stdin убудований текст для

      - 12 керування властиво редактором. Еd читає команди, як якби вони були дані із клавіатури. Він не знає, що запущено в командному режимі. Це відкриває зовсім новий спосіб використання моці інтерактивного редагування в командному режимі.
      Як приклад розглянемо наступну програму. Помнете, що всі спеціальні символи в мові shell повинні бути укладені в кавычки, наприклад $. Якщо вони не укладені в лапки, то уведення буде некорректным.

      ed file << -!
      1, \$s/^ *//
      w
      q
      !
У цьому прикладі редагується файл за назвою "file" і над ним виконується кілька команд. Перша команда говорить "Від першої рядка до останньої, для кожного рядка, що має порожні символи в початку рядка, за яких треба будь-яка кількість таких же символів, замінити ці символи "нічим". Запишіть файл і вийдіть." Ця процедура видаляє пробіли з початку рядка.


      З файлом a.out

      Можливість убудованого тексту також можна використовувати, щоб автоматизувати запуск програм. Вам потрібно записати вхідні дані, необхідні, щоб програма виконувала бажане завдання, і помістити їх у текст програми. (Це щось начебто побудови макросів клавіатури для прикладних програм для PC).
      У наступному прикладі виконується файл, щоМ, a.out запускається як дочірній shell. Його уведення береться із самого файлу, а висновок передається команді more, так що ми можемо зробити посторінковий висновок.

      $ (a.out <      > text
      > input
      > lines
      > !
      ) | more

      Це можна надрукувати безпосередньо із клавіатури. Ми використовуємо символи дужок, оскільки, якщо безпосередньо друкувати цей код, shell буде видавати підказку PS2 аж до знака !, потім виконає команду. Єдине, що ми можемо зробити, щоб він не вийшов автоматично - це продовжувати запитувати уведення, опускаючи його на рівень нижче.


      C архівами мови shell

      Архіви мови shell - це один з найпростіших способів упаковать текст у самоустановлювальну програму. Ідея полягає в тому, що ми використовуємо командний файл мови shell, щоб упакувати деякий текст. Цей текст може бути документом, командним файлом або навіть вихідним текстом програми.

      Ми використовуємо конструкцію убудованого тексту, щоб передати текст в shell, що потім пересилає його у визначені файли. Нижче наведений приклад архіву, що може бути у файлі.

      $ cat archive


      - 13
      #
      # Це архівний файл текстових файлів 1, 2 і 3
      #

      echo "витягаємо текстовий файл 1"
      cat > text1.sh << !
      #
      # Це приклад текстового файлу 1
      #

      who | sort
      !
      echo "витягаємо текстовий файл 2"
      cat > text2 << !

      Цей уміст другого файлу. Це не програма, а просто текст.
      Помітьте, що йому не потрібно рядків коментарю, тому що
      запущений shell знає, що це уведення. Але не намагайтеся запускати
      text2, тому що у Вас однаково нічого не вийде.

      !

      echo "витягаємо текстовий файл 1"
      cat > text3.c << !

      /* Цей уміст файлу 3, Си програма */

      main()
      {
      printf("hello world");
      }
      !

      #
      # кінець архівного файлу
      #

      При виконанні архів проходить через три команди cat. Перша доманда cat створює файл text1.sh (командний файл мови shell), text2 (звичайний текст) і text3.c (Сі-програма). Все це виконується після того, як Ви наберете на клавіатурі "archive". Це зручно, якщо потрібно перенести текст в інше місце. Замість того щоб пересилати три фаїла, нам потрібно переслати один. Замість трьох файлів, з'єднаних разом, у нас три окремо упакованнных файли, кожний з яких восстанавливает себе при запуску архіву. Таким чином, нам не прийде ворожити, намагаючись представити який текст у який файл потрапить.


      Керування статусом циклу

      Іноді умовні вираження циклу потрібно підбирати спеціальним образом, щоб вони відповідали нашим потребам. Це відбувається не часто, однак бувають ситуації, коли Ви можете захотіти використовувати певний синтаксис. У таблиці 10-1 наведені три різних способи зробити умова циклу while "щирим". Помнете, що shell шукає успішний статус виходу - статус (0) з останньої синхронно виконуваної команди.
Таблиця 10-1 Способи змусити цикл бути "щирим"
+-і-і-і-і-і-і-і+-і-і-і-і-і-і-і-і-і-і-і-і-і-і-і-і-і-і-і-і+ | Цикл | Умова зі значенням "істина" |

      - 14 +-і-і-і-і-і-і-і+-і-і-і-і-і-і-і-і-і-і-і-і-і-і-і-і-і-і-і-і+ |while true |True - це команда в /bin, що віз-| | |вращает статус 0 | |while[1 -eq 1]|мы використовуємо тут тестову команду, | | |чтобы повернути статус 0 | |while : |мы використовуємо убудовану пропозицію | | |shell'а, щоб повернути статус 0 | +-і-і-і-і-і-і-і+-і-і-і-і-і-і-і-і-і-і-і-і-і-і-і-і-і-і-і-і+


      Фільтри й синтаксис

      Раніше в цій книзі вже йшла мова про фільтри. Не всі команди є фільтрами або можуть бути використані як фільтри. Згадаєте визначення фільтра - це команда, що бере уведення з аргументів командного рядка, якщо вони є. Інакше уведення читається з стандартного уведення.
      Чому всі команди не можуть діяти як фільтри? Тому, що вони не призначені для цього. Візьмемо, наприклад, ls. Що робить ls? Вона видає список файлів у поточному каталозі. Якщо ми говоримо "ls file", він видає інформацію тільки для цього файлу. Якщо ми говоримо "echo file | ls", ls не подає інформацію про файл, але видає список файлів у поточному каталозі, тому що ls не дивиться в стандартний уведення, якщо в командному рядку немає аргументів.

      Один важливий момент, пов'язаний з фільтрами - це спосіб їхнього виклику. Якщо Ви поміщаєте ім'я файлу в командний рядок, фільтр відкриває файл і читає дані. Помнете, що фільтри хочуть читати дані. Якщо Ви приєднуєте стандартне уведення до фільтра, воно думає, що те, що він читає із програмного каналу- це дані. Якщо Ви дасте фільтру імена файлів, Ви не одержите того результату, що очікуєте. Давайте розглянемо кілька прикладів. Команда UNIX wc - це фільтр. Ми можемо викликати її як "wc file1 file2 file3", щоб вона підрахувала слова в трьох файлах. Що було б, якби ми сказали: "ls file1 file2 file3 | wc" ? Wc підрахувала б суму символів, які видала б ls. У цьому випадку в рядку file1, file2, і file3 - 15 символів. Як нам одержати реальні файлові дані, а не імена файлів в wc? Змінюючи спосіб, яким ми викликаємо wc:

      cat file1 file2 file3 | wс

      Шляхом попереднього з'єднання файлів, дані передаються на вхід wc, і wc підсумує підраховані суми символів, умісту файлів. Та ж сама концепція застосовна для всіх команд фільтрів. Ще одною подібною командою є awk. Ми можемо сказати "awk file", і команда прочитає вміст файлу, або "cat file | awk", і одержимо такий же результат. Ми не можемо використовувати синтаксис "ls file | awk", т.к. awk виконує свою програму тільки над символами в ім'ї "file".


      Недоліки/особливості програмування мовою shell

      У цьому розділі ми розглянемо деякі недоліки мови shell. До кінця поки не ясно, чому проявляються ці дефекти або особливості. Так уже shell працює й такий вуж він насправді.


      Програма для перенапрямку помилки

      1 :
      2 # @(#) перенапрямок помилкового значення змінної в цикл,
      приєднаний до програмного каналу
      3
      4 N=1
      5 echo "початкове значення N = $N"
      6
      7 echo "1\n2\n3" | while read LINE
      8 do
      9 N=2
      10 echo "значення в циклі N = $N"
      11 done
      12
      13 echo "кінцеве значення N = $N"

      Програма показує, що різні присвоєння, зроблені в дочерних мовах shell, не поширюються на їхніх батьків. Рядок 4 привласнює N початкове значени 1. Потім значення N відображається в рядку 5 для перевірки. Вся хитрість цієї програми укладена в рядку 5. Ми відправляємо символи "1 новий рядок 2 новий рядок 3" у программный канал і даємо це на вхід циклу while. Таким чином, ми змушуємо цикл виконати три ітерації. Приєднуючи висновок до програмному каналу, ми створюємо дочірній shell, щоб виконати цикл while. Усередині циклу while ми змінюємо значення N і друкуємо його для проверки.
      Наприкінці циклу ми друкуємо остаточне значення N. Воно більше не дорівнює 2 як це було усередині циклу, а дорівнює 1, як це було після першого присвоєння. Нижче представлений приклад прогону цієї програми.

      $ redir
      начально значення N = 1
      значення в циклі N = 2
      значення в циклі N = 2
      значення в циклі N = 2
      кінцеве значени N = 1
Це показує, що значення змінної передається долілиць дочірньому мові shell, але зміни в дочірньому shell не передаються родительскому.


      Некоректний код повернення

      Звідки shell знає, чи є коректними ті або інші коди повернення? На це складно відповісти. Іноді виявляється, що код помилковий, коли помилку містить ваша програма.
Наприклад:
1 : 2 # @(#) помилка коду повернення 3 4 echo "Уведіть команду : \з" 5 read CMD 6 7 eval $CMD 8 echo "\$? = $?" 9 10 if [ $? -eq 0 ] 11 then echo гарний вихід - $? 12 else echo поганий вихід - $? 13 fi

      Програма починається з того, що в рядку 4 Вам видається підказка для введення команди. Команда читається, рядок 7 оцінює не потрібні чи їй додаткові змінні й виконує її. Помнете, що нам потрібно оцінити параметр у тому випадку, якщо хто-небудь сказав щось типу "echo $HOME". Якщо команди eval ні, то друкується

      - 16 літеральний рядок $HOME. Після команди eval друкується дійсне значення $HOME. Так що нам доводиться використовувати команду eval у цій ситуації. Після того як команла виконаний рядок друкує статус виходу, посилаючись на $?. Це зовсім нормально. Рядок 10 потім використовує тестову команду, щоб програма розгалузилася залежно від коду повернення. Це і є те місце, де помилка. Величина, що бачить тестова команда не збігається з тієї, яку друкує луна.

      $ status
      уведіть команду: ls -z
      ls : illegal option -іz
      usage : -1ACFRabcdfglmnopqrstux [files]
      $? = 2
      гарний вихід - 0

      Це показує, що ls запустили в помилковому режимі. Ls надрукував своє повідомлення про помилку й повернув код повернення рівний 2. Однак тестова команда бачить $? як значення 0 і вибирає галузь істина. Чи можете ви знайти помилку в рядку 8 програми ? Це гарна нота для закінчення роздягнула про помилки.


      Хитрості редактора Vi

      Одна із самих чудових особливостей UNIX - це можливість вийти із програм так, щоб Ви могли запускати інші команди поза мови shell. Це було розроблено усередині UNIX і є простим і потужним засобом. Використання деяких прийомів, описаних нижче может зробити розробку програми більше простій і швидкої.


      Повернення в shell

      Повернення в shell - дуже корисна можливість у редакторі vi. Ви можете записати Вашу програму в редакторі, вийти з нього, запустити програму, повернутися назад у редактор і т.д. Цей цикл редагування - трансляція - перевірка може бути виконаний з редактори. Із цими можливостями входу й виходу з редактора Ви можете закінчити сеанс роботи без реального знищення редактора.
      Редактор vi також є редактором ex. Vi - це візуальна частина ex. Отже, Ви можете вийти в shell двома шляхами.
      Перший - використовуючи змінну sh, що встановлена в редакторі ex. Ви можете набрати

      : sh
поки ви в vi або просто "sh", якщо Ви в ex. Редактор прямо залишає shell, що Ви визначили в змінної sh. Звідки редактор знає який shell Ви запускаєте? Це можна визначити по реєстраційної змінної оточення мови shell. Якщо Ваш shell - /bin/sh, а Ви хотиті запустити /bin/shV, Ви можете переустановити значення змінної, надрукувавши ":set sh=/bin/shV"

      Інший спосіб виходу з vi - це з використанням синтаксису:

      :!sh
де "sh" дає Вам shell (/bin/sh). Зверніть увагу, що відбувається. Ви запускаєте shell (запуска_ по :!), якому дана команда запустити shell (:!sh). Коли Ви, нарешті, запукаете цей shell, виходить, що у Вас запущений зайвий shell. Це дуже наочно представлено в лістингу ps, наведеному нижче

      - 17
UID PID PPID C STIME TTY TIME COMMAND russ 35 1 0 Jul 5 co 0:50 -shv russ 1233 35 0 04:30:15 co 0:57 vi file russ 1237 1233 0 04:43:13 co 0:01 sh -c sh russ 1238 1237 0 04:43:15 co 0:02 sh

      У третьому рядку все сказано. З vi ви запустили shell з опцією -із для запуску мови shell . Це марна витрата цілого shell! А якщо використовувати зазначений вище синтаксис або просто ":sh", то така ситуація не виникне.


      Підтримка Escape

      Крім того, що редактор vi можна покинути по Esc, він підтримує деякі інші можливості для виходу. Володіючи різними можливостями виходу, інструментальні засоби можуть виконувати для Вас більшу частину роботи. Перший варіант синтаксису ":!cmd", що є префіксом для запуску будь-якої команди поза редактори. У цьому випадку команда може бути будь-якою командою роздягнула (1).
      Другий варіант синтаксису - це ":!!". Це означає вийти (:!) і використовувати останній командний рядок як аргумент для запуску в новій мові shell. Наприклад, якщо ми сказали: ":!ls", потім ":!!", :ls буде запущена знову. Другий ! посилається до всій попередній домандной рядку.
      Третій варіант синтаксису - це ":! %". Це означає вийти (:!) і запустити команду, ім'я якої є ім'ям цього файлу (%). Коли ви натискаєте повернення каретки, % - заміщається ім'ям файлу, що дуже зручно при редагуванні командних файлів. Ви можете зробити що-небудь типу:

      $ vi tool
      . . . edit . . .
      :w

      Ви викликаєте vi з ім'ям файлу, так що vi запам'ятовує ім'я "tool" у своєму буфері. Ви можете змінити щось прямо отут в редакторі, записати зміни на диск, потім запустити нову копію файлу. Редактор заповнює файл із ім'ям "tool" і запускає його. Коли Ви виходите з файлу, що виконується, "tool", Ви попадаєте назад в редактор, готові внести зміни в текст і запустити програму знову.
      Одна з гарних послідовностей - це відредагувати файл, зробити зміни, записати їх, запустити файл, використовуючи %, внести зміни ще раз, запустити знову програму, надрукувавши :!!, що перезапускає останню команду escape, :! % . У такий спосіб цикл виходів і запусків програми утворить три натискання клавіатури, :!!.
      Ми навіть можемо використовувати цю можливість для компіляції програм на С. Якщо в нас є командний файл, що називається "cg" (генератор компіляції) ми можемо простіше використовувати vi:

      F = 'echo $ 1 | sed -e "s/^\(.*\).c$/\1"'
      cc $1 -o $F

      Потім ми можемо виконати послідовність такого типу:

      $ vi test.c
      ...edit...
      :!cg %
або те ж саме коротше

      - 18

      : !cg test.c
і закінчується створенням модуля, що виконується, "test".


      Макроси

      Інша можливість vi, що підтримує простий вихід, - це механізм макросів. Хоча головним чином макроси потрібні для того, щоб можна було поміщати команди редагування в іменовані регістри, які часто використовуються. У такий спосіб замість того, щоб використовувати синтаксис знову й знову, Ви просто використовуєте макрос. Нижче наведений приклад макропідстановки:

      i
      s/^[^ ]*/ [^ ]*/
      "add
      @a

      Спочатку потрібно перейти в режим вставки, щоб ми могли помістити команду в наш файл редактора. Ми друкуємо команду підстановки й натискаємо ESC, щоб закінчити роботу в режимі вставки. Команда підстановки говорить "У рядках, які починаються з непустого символу, за яким ідуть один або кілька символів такого ж типу, поставити пробіл перед непустою послідовністю символів". Далі ми друкуємо "add", де "а" позначає іменований регістр a і dd позначає перемістити рядок у буфер. Тепер рядок підстановки перебуває в буфері а. Щоб неї виконати ми просто надрукуємо @a в командному режимі vi.

      Щоб вийти ми можемо виконати ту ж послідовність дій, але помістити команду типу

      :!ps -ef
у редактор і переписати її в буфер. Потім, коли ми говоримо @a, ми входимо в shell і запускаємо команду ps. Команди такого типу можна поміщати в іменовані буферы від a-z.

      Останній спосіб використання макросів для підтримки виходу - це через команду map. Ця команда є в ex і адресується попередньої двокрапкою : з vi. Синтаксис для команди map виглядає так:

      :map lhs rhs

      Це встановлює відображення лівої сторони на праву сторону. Приклад присвоєння виглядає так:

      :map w :!who^M

      Тепер щораз, коли Ви друкуєте w, буде виконуватися дія виходу через ex, друкуватися команда who, потім друкуватися повернення каретки, що відправляє всю цю послідовність на виконання. Все це по одному натисканню клавіатури.
      Саме смішне починається, коли Ваш термінал має функціональні клавіші. Vi звертається до функціональних клавіш по #0 -#9. Тепер ми можемо зарезервувати функціональні клавіші для команд виходу. Просте присвоєння буде:

      :map #1 :!ps -ef^

      Щораз, коли Ви натискаєте функціональну клавішу F1,

      - 19 запускається команда ps -ef.


      Команда "One-Liners" - малюсінька, але потужна

      Наступний список - це добірка звичайних команд, використаних таким чином, щоб одержати потужний ефект. Як майстер військового мистецтва, що вбиває голими руками, майстер UNIX часто може скласти разом кілька звичайних команд і досягти колосального ефекту. Деякі рядки, які будуть представлені нижче, можна зустріти в інших місцях цієї книги, але вони приводяться тут повторно для полегшення пошуку.
      Рядки групуються відповідно до команди, що є ключовий у даному рядку, однак, іноді складно виділити таку команду як, наприклад, у випадку програмного каналу, коли Ви із двох сторін маєте важливі команди. Помітьте, що деякі із цих команд є стандартними командами UNIX, у той час як інші - це командні файли й програми, представлені раніше в цій книзі.

ACCTCOM
* прочитати всю Вашу облікову інформацію, починаючи з останньої команди.

      acctcom -b -u$LOGNAME
* показати всі облікові записи, запущені з Вашого термінала й того,
      який запущений як суперкористувач

      acctcom -u# -l'tty'

BANNER
* надрукувати повідомлення на трьох рядках

      banner "line 1" "line2" "line3"
* надрукувати день тижня й дату на одному рядку, час на інший

      banner "'date|cut -d' ' -f1,3'" "'date|cut -d''-f4'"
* послати повідомлення на екран іншого користувача

      banner "Привіт" "там" > /dev/tty01

BASENAME
* очистити шлях

      echo "Я за пристроєм 'basename\'tty\' ' ''

BC
* передати формулу на вхід команді bc, що повинна виконати
      множення й привласнить результат PROD

      PROD = 'echo $NUM1 * $NUM2 | bc'

CAT

      - 20

      * передати символи із клавіатури у файл

      cat > file (друкувати поки не зустрінеться символ ^D
      для припинення читання)

      * одержати уведення з конструкції "документ тут"
      cat << -!
      Це зразок тексту, що друкується на екрані !

CC
* множинна компіляція у фоновому режимі з однієї командної
      рядка

      cc file1.c & cc file2 & cc file3.c &

CD
* перейти в каталаг, у якому перебуває файл

      cd 'ім'я директорія\'шлях файл\''
* перейти в каталог, що записаний у змінної

      DESTINATION="/usr/bin"
      cd $DESTINATION
* перейти в каталог, записаний у файлі

      cd 'cat dest_file'

CHMOD
* включити біт виконання файлу

      chmod +x file
* включити біт зміни ідентифікатора користувача й дозволити
      усім виконання файлу

      chmod 4755 file
* установити біт sticky у включений стан

      chmod 1755 file

CHOWN
* установити себе власником файлу

      chown $LOGMAME files
* тим же саме іншим способом

      chown 'who am i| cut -d' '-f1' files
* змінити право власності для дерева


      - 21
      cd dest
      find . -print | sort | while read FILE
      do
      chown russ $FILE
      done

CP

      * скопіювати три рівні файлів в один вкаталог /tmp
      cp */*/* /tmp

      * тим же саме іншим способом
      cp 'find . -type f -print' /tmp

      * перемкнути користувальницька пропозиція
      cp -z

CPIO

      * перемістити дерево системи файлів у нове місце розташування
      cd $SRC
      find .-print | sort | cpio -pdv $DEST

      * скопіювати дерево системи файлів на гнучкий диск
      cd $HOME
      find .-print | sort | cpio -ocBv > /dev/rfd0

      * відновити копію на стримере
      cd $DEST
      cpio -icBvt < /dev/rfd0

      * виконати "ls -l" на копії стримера
      cpio -icBvt < /dev/rfd0

CRON

      * запустите Ваш генератор повідомлень про статус щочетверга
      в 6:00 a.m.
      0 6 * * 4 /usr/russ/bin/status_msg

      * chmod на файл паролів

      * * * * * /bin/su root -c "chmod 777 /etc/passwd"
CU

      * безпосередньо звернутися послідовному порту на швидкості
      1200 бод

      cu -ltty00 dir

      * безпосередньо звернутися до послідовного порту на швидкості
      9600 бод

      cu -ltty00 -s9600 dir

      * автоматично викликати іншу систему, використовуючи комбінацію
      dial/modem

      cu -acua0 555-1212

      - 22

CUT

      * відітнути перше поле з файлу passwd

      cut -d: -f1 /etc/passwd

      * відітнути ім'я з лістингу команди who

      who | cut -d' ' -f1
      who | awk '{print $1}

DD

      * повна гнучка копія доріжка за доріжкою

      dd if = /dev/fd0 of=/dev/fd1

DOS

      * скопіювати всі файли даного каталогу на дискету DOS

      doscp * a:

      * скопіювати всі файли з дискети DOS у даний каталог
      dosls a: > /tmp/dosf
      for FILE in 'cat /tmp/dosf'
      do
      doscp a:$FILE
      done

DU

      * видати загальна кількість блоків для всіх каталогів в /

      du -s /*

      * надрукувати кількість використаного місця в каталозі
      кожного користувача

      echo "total bytes: 'expr\'du -s $1\' \* 512'"

ECHO

      * надрукувати значення змінної shell'а
      echo $PATH $CDPATH

      * надрукувати висновок упереміш зі звичайним текстом

      echo " Моє ім'я $LOGNAME або
      'logname' або 'who am i|cut -d' ' -f1'"

      * надрукувати символи упраления в лапках і без

      echo "\n\t Це записано в лапках"
      echo \\n\\t Це записано без лапок

      * надрукувати й залишити курсор наприкінці того ж рядка

      - 23

      echo -n "prompt: "
      echo "prompt: \c"

ED

      * запустити ed автоматичски з конструкцією
      "документ тут"

      ed /etc/passwd <<-!
      1,$p
      g/root/s//noroot
      w
      q
      !

EXPR

      * помножити два числа
      expr 512 \* 1024

      * збільшити змінну на визначене значення

      x = 0; INC = 5
      X='expr $X + $INC'

FILE

      * знайти всі текстові файли
      file * | fgrep text

      * надрукувати імена тільки текстових файлів
      file * | fgrep text | cut -d: -f1

      * more всі текстові файли
      more 'file * | fgrep text | cut -d: -f1'

FIND

      * знайти всі файли в системі
      find / -print | sort

      * знайти всі файли й роздрукувати список у форматі long
      find / -exec ls -ld {} \;

      * надрукувати імена всіх регулярних файлів
      find / -type f print

      * знайдіть всі каталоги й роздрукуйте вміст
      find / -type d print | while read DIR
      do
      echo "listing $DIR"
      ls $DIR
      done

      * знайдіть всі файли, які були модифіковані в останні
      24 години й роздрукуйте їхній список у форматі long
      find / -atime -0 -exec ls -ld {} \;


      - 24
      * знайдіть всі файли setuid і setgid
      find / -perm -4000 -o -perm -2000 -exec ls -ld {} \;

FINGER

      * укажіть всіх користувачів, що вийшли із системи
      finger 'who | cut -d' ' -f1'

      * укажіть всіх користувачів у файлі passwd
      cut -d: -f1 /etc/passwd | while read NAME
      do
      finger $NAME
      done

GREP

      * знайти випадки вживання шестнадцатиричных чисел у файлі
      даних
      od -x datafile | grep 'A3F09'

      * знайти своє ім'я в системі
      find / -type f print | while read FILE
      do
      grep "russ" $FILE /dev/null
      done

HEAD

      * озаглавте всі текстові файли в поточному каталозі
      file * | fgrep text | cut -d: -f1 | while read FILE
      do
      echo "-і-і-і-і"
      echo "$FILE"
      echo "-і-і-і-і"
      head "$FILE"
ID

      * визначити, хто в цей момент є суперкористувачем
      if [ "'id'" = "uid=0(root) gid=0(root)" ]
      then echo "you are root"
      fi

      * тим же саме іншим способом
      if id | fgrep root > /dev/null
      then echo "you are root"
      fi
KILL

      * знищте себе (вивантажите)
      kill -9 0
      kill -9 $$

      * завершите роботу системи
      kill -1 1

      * знищте останній процес, запущений у фоновому режимі
      kill -9 $!


      - 25
      * знищте процес, ідентифікатор якого перебуває у файлі
      kill -9 'cat idfile'

LINE

      * взяти рядок з термінала
      LINE='line < /dev/tty'

      * взяти рядок зі стандартного уведення
      cat datafile | while LINE = 'line'
      do
      echo $LINE
      done

LOGIN

      * перейти зі сгенерированной підказки login ???

      login: ^d
      login:

      * одержати деяку внутрішню інформацію
      (програма strings - це BSD)

      strings /bin/login | more

LOGNAME

      * надрукувати інформацію про свій пароль
      grep '^'logname ':' /etc/passwd

      * одержати інформацію про свій процес
      ps -fu 'logname'

LS

      * видати список схованих файлів
      ls -ad .*

      * видати розмір файлу в байтах
      ls -l file

      * видати розмір файлу в блоках
      ls -s file

      * видати інформацію про права доступу по записі всіх
      зарегестрировавшихся в системі
      ls -li 'who |sed "s/^[^ ]* *\([^ ]*\) .*$/\/dev\/\1/p"'

      * одержати допомогу по испоьзованию команди
      ls -z

      * видати список тільки каталогів
      ls -al |grep "^d"

MAIL

      * послати пошту всім користувачам

      - 26
      cut -d: -f1 |while read USER
      do
      echo "mailing to $USER"
      mail $USER
      done

      * послати пошту з файлу
      mail russ < /etc/passwd

      * послати пошту із програмного каналу
      echo "Це текст пошти" | mail russ

MORE

      * надрукувати всі файли поточного каталогу
      more *

      * надрукувати 10 рядків за раз
      more -10 file
      cat file | more -10

MKDIR

      * опуститися на максимальну глибину
      while :
      do
      mkdir x
      cd x
      done

      * тим же саме іншим способом
      PATH="x"
      while :
      do
      mkdir $PATH
      PATH="$PATH/x"
      done

NCHECK

      * знайти всі файли, приєднані до vi
      ls -li /bin/vi
      40 -rwwx--x--t 1109344 Feb 14 1985 /bin/vi
      ncheck -i 40 /dev/root

      * знайти всі файли установки ідентифікатора користувача
      ncheck -s

NM

      * подивитися символьні таблиці всіх nonstripped
      файлів, що виконуються

      nm 'file *| grep "not stripped"|sed "s/^\(.*\):.*$/\1/"

OD

      * подивитися символи в іменах файлів у поточному каталозі

      - 27
      od -c .

      * надрукувати значення функціональних клавіш, комбінацій
      клавіш, і.т.буд.

      od -cb (натисніть комбінацію клавіш)

      ^d (друкує рядок)
      (натисніть що-небудь ще)
      ^d (друкує наступний рядок)
      ^d (выыходит з od)

      * зробити дамп копії на стримере
      od -c /dev/rfd0

      * зробити дамп файлової системи
      od -c /dev/root

PASSWD

      * як суперкористувач Ви можете встановити як пароль
      будь-який рядок

      # passwd russ
      Changing password for russ
      (Зміна пароля для russ)
      Enter new password (minimum of 5 characters)
      (Уведіть новий пароль (мінімум 5 символів))
      Please use combination of upper, lowercase letters
      and numbers
      (Прохання використовувати комбінації чисел і букв в
      верхньому й нижньому регістрах)
      New password: junk
      (Новий пароль: junk)
      Re-enter new password: junk
      (Новий пароль: junk)
      #

      * як звичайний користувач Ви повинні будете вводити пароль із обліком
      кількісних обмежень і обмежень по довжині

      $ passwd russ
      Changing password for russ
      (Зміна пароля для russ)
      Enter new password (minimum of 5 characters)
      (Уведіть новий пароль (мінімум 5 символів))
      Please use combination of upper, lowercase letters
      and numbers
      (Прохання використовувати комбінації чисел і букв в
      верхньому й нижньому регістрах)
      New password: junk
      (Новий пароль: junk)
      Too short. Password unchanged.
      (Занадто короткий. Пароль не змінений)
      $

PR

      * вивести многоколоночный список імен файлів
      ls $@ | pr -5t
      * надрукувати файли зі списку

      - 28
      pr 'find . -name "*.c" -print | sort'

PS

      * надрукувати повну інформацію про всі активні процеси
      ps -aef

      * надрукувати інформацію про всі процеси, керованих
      Вашим терміналом
      ps -f

      * надрукувати інформацію про процеси, пов'язаних з терміналом tty00
      ps -ft00

      * надрукувати інформацію про процеси, пов'язаних з користувачем russ
      ps -furuss

      * BSD синтаксис для печатки всіх процесів
      ps -aux

      * BSD синтаксис для печатки всіх процесів, пов'язаних з
      термінальним пристроєм
      ps -xut00

PWD

      * зберегти поточний робочий каталог
      PWD='pwd'

      * повернутися в раніше збережений робочий каталог
      cd $PWD

RM

      * видалити всі файли, крім каталогів з файлами
      rm *

      * видалити порожні каталоги
      rmdir dirs

      * видалити каталоги, що мають файли
      rm -r dirs

      * видалити всі файли в режимі, коли система не буде
      задавати ніяких питань
      rm -rf *

      * видалити кожний файл у системі окремо
      rm -rf /




SH

      * прочитати список поэлементно

      for ELEMENT in 'cat /etc/motd'
      do

      - 29
      echo $ELEMENT
      done


      * прочитати список построчно
      cat /etc/motd | while read LINE
      do
      echo $LINE
      done

      * цикл поки - назавжди (while-forever)
      while :
      do
      echo $PS1
      read CMD
      case $CMD in
      "") break;;
      esac
      done

      * керований цикл while
      read CMD
      while [ "$CMD" != ""]
      do
      case $CMD in
      user-cmd) do_it;;
      esac
      echo $PS1
      read CMD
      done

      * переполнениие тестового стека при обробці
      переривання
      trap "echo trapping; kill $$" 2 3 15

      * вивантаження з мови shell декількома способами

      exit
      eof character (usually control -d)
      kill -9 0
      kill -9 $$

STTY
      * подивитеся всі свої установки
      stty -a

      * подивитеся термінальні установки
      іншого термінала
      stty -a < /dev/tty01

      * установити передачу бод на іншу швидкість для
      іншого термінала
      stty 300 < /dev/tty01

      * динамічно встановити control-A як клавішу
      переривання
      stty intr ^a

      * включити луну-супровід термінала
      stty -echo



      - 30 SU

      * тестовий цикл для знищення легких паролів

      awk '{FS =":"; print $1,$5} '/etc/passwd|while read N C
      do
      echo "\n$N\t$C"
      su $N
      done

TAIL

      * простежити в реальному часі запис шипиків файлу
      входу в систему (logfile) uucp

      tail -f /usr/spool/uucp/LOGFILE

      * подивитися останній рядок файлу
      tail -1 file

      * подивитися останні 10 символів змінної
      echo "$VAR" | tail -10c
TAR

      * зробити копії файлів у Вашім home-каталозі не розриваючи файл, але
      формуючи копії на шматки по 1200 блоків
      cd
      tar cvefbk /dev/rfd0 10 1200 .

      * виконати команду "ls-l" для копій файлів
      tar tvf /dev/rfd0

      * відновити копії файлів
      cd $DEST
      tar xvf /dev/rfd0

      * скопіювати файли в tar , відсортувавши їх
      tar cvfk /dev/rfd0 1200 'find . -print | sort'

TEE

      * відправте свій висновок на екран іншого термінала
      sh | tee /dev/tty01

      * захопите висновок інших команд
      fsck /dev/root | tee capture
      cu -ltty00 dir | tee capture

TEST

      * перевірте еквівалентність двох рядків
      test "$S1" = "$S2"

      * перевірте еквівалентність двох чисел
      test "$N1" -eq "$N2"

      * тим же саме іншим способом
      (помітьте що /bin/[приєднано до /bin/test)


      - 31
      [ "$S1" = "$S2" ]
      [ "$N1" -eq "$N2" ]

TOUCH

      * зробіть поточний доступ і зміните час всіх файлів у Вашім
      home каталозі

      find $HOME -exec touch {} \;
      find $HOME -print | while read FILE
      do
      touch $FILE
      done

TTY

      * показати права доступу по записі на Вашім терміналі
      ls -l 'tty'

      * включити й відключити доступ користувачів до Вашого термінала
      chmod 666 'tty'
      chmod 600 'tty'

UUCP

      * скопіювати імена всіх файлів у файл у загальнодоступний каталог на
      іншій системі

      for FILE in 'cat datafile'
      do
      echo "копіювання $FILE"
      uucp $FILE sys! ~/user
      done

      * поставити файл у чергу, не ініціювати виклик, взяти файл із
      Вашого первісного каталогу, не копирровать його в spool
      каталог.
      uucp -r -c file sys!/tmp

VI

      * виконаєте поточний рядок як команду мови shell
      :.w !sh

      * тим же саме іншим способом, використовуючи макрос
      "ayy
      @a

      * вийти безпосередньо в shell
      :sh

      * скомпілювати поточний файл
      :!sh

      * запустити ім'я поточного файлу як комаду мови shell
      :!cc %

      * запустити ще раз останню команду
      :!%

      - 32

      * запустити команду й помістити ввывод на поточну
      рядок (переписати)
      :.!who am i

      * запустити команду й помістити ввывод на новий рядок
      :.r !who am i
      :r !who am i

      * відредагувати файл, що перебуває десь в
      системі
      :e 'path termcap'

      * помістити long лістинг файлу, що перебуває
      десь у файлі редактора
      :.!ls -l 'path init'

WC

      * друкує кількість людин, зареєстрованих у системі
      echo "Усього 'who | wc -l' людина ввійшла в систему"

      * друкує кількість сторк у всіх вихідних файлах
      find /usr/src -name "*.c" -exec cat {} \; | wc -l

WHO

      * друкує кількість і імена зареєстрованих
      користувачів
      who | awk '{ print "user:",$1,"\tdevice:",$2
      cnt = cnt + 1
      } END { print cnt,"користувачі, що вийшли із системи"}'

      * друкує
      who | while read NAME TTY TIME
      do
      echo "користувач: $NAME tty: $TTY time: $TIME
      done
[...]
Початок
[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] [32] [33] [34] [35] [36] [37] [38] [39] [40] [41] [42] [43] [44] [45] [46] [47] [48] [49] [50] [51] [52] [53] [54] [55] [56] [57] [58] [59] [60] [61] [62] [63] [64] [65] [66] [67] [68] [69] [70] [71] [72] [73] [74] [75] [76] [77] [78] [79] [80] [81] [82] [83] [84] [85] [86] [87] [88] [89] [90] [91] [92] [93] [94] [95] [96] [97] [98] [99] [100] [101] [102] [103] [104] [105] [106] [107] [108] [109] [110] [111] [112] [113] [114] [115] [116] [117] [118] [119] [120] [121] [122] [123] [124] [125] [126] [127] [128] [129] [130] [131] [132] [133] [134] [135] [136] [137] [138] [139] [140] [141] [142] [143] [144] [145] [146] [147] [148] [149] [150] [151] [152] [153] [154] [155] [156] [157] [158] [159] [160] [161] [162] [163] [164] [165] [166] [167] [168] [169] [170] [171] [172] [173] [174] [175] [176] [177] [178] [179] [180] [181] [182] [183] [184] [185] [186] [187] [188] [189] [190] [191] [192] [193] [194] [195] [196] [197] [198] [199] [200] [201] [202] [203] [204] [205] [206] [207] [208] [209] [210] [211] [212] [213] [214] [215] [216] [217] [218] [219] [220] [221] [222] [223] [224] [225] [226] [227] [228] [229] [230] [231] [232] [233] [234] [235] [236] [237] [238] [239] [240] [241] [242] [243] [244] [245] [246] [247] [248] [249] [250] [251] [252] [253] [254] [255] [256] [257] [258] [259] [260] [261] [262] [263] [264] [265] [266] [267] [268] [269] [270] [271] [272] [273] [274] [275] [276] [277] [278] [279] [280] [281] [282] [283] [284] [285] [286] [287] [288] [289] [290] [291] [292] [293] [294] [295] [296] [297] [298] [299] [300] [301] [302] [303] [304] [305] [306] [307] [308] [309] [310] [311] [312] [313] [314] [315] [316] [317] [318] [319] [320] [321] [322] [323] [324] [325] [326] [327] [328] [329] [330] [331] [332] [333] [334] [335] [336] [337] [338] [339] [340] [341] [342] [343] [344] [345] [346] [347] [348] [349] [350] [351] [352] [353] [354] [355] [356] [357] [358] [359] [360] [361] [362] [363] [364] [365] [366] [367] [368] [369] [370] [371] [372] [373] [374] [375] [376] [377] [378] [379] [380] [381] [382] [383] [384] [385] [386] [387] [388] [389] [390] [391] [392] [393] [394] [395] [396] [397] [398] [399] [400] [401] [402] [403] [404] [405] [406] [407] [408] [409] [410] [411] [412] [413] [414] [415] [416] [417] [418] [419] [420] [421] [422] [423] [424] [425] [426] [427] [428] [429] [430] [431] [432] [433] [434] [435] [436] [437] [438] [439] [440]