Content from Знайомство з терміналом
Останнє оновлення 2025-03-10 | Редагувати цю сторінку
Приблизний час: 5 хвилин
Огляд
Питання
- Що таке командний термінал і навіщо його використовувати?
Цілі
- Пояснити, як термінал пов’язаний з клавіатурою, екраном, операційною системою та програмами користувача.
- Пояснити, коли та чому інтерфейси командного рядка слід використовувати замість графічних інтерфейсів.
Попередні знання
Люди та комп’ютери зазвичай взаємодіють багатьма різними способами, наприклад за допомогою клавіатури та миші, сенсорного екрану або системи розпізнавання мови. Найбільш поширений спосіб взаємодії з персональними комп’ютерами називається графічний інтерфейс користувача (GUI - graphical user interface). За допомогою такого інтерфейсу ми надаємо комп’ютеру інструкції, обираючи дію у меню за допомогою миші.
Хоча візуальна допомога графічного інтерфейсу користувача робить інтуїтивним його вивчення, такий спосіб надсилання інструкцій до комп’ютера дуже погано масштабується. Уявіть наступну задачу: для бібліографічного пошуку вам необхідно скопіювати третій рядок з тисячі вхідних файлів з тисячі різних директорій та вставити усе це в один файл. Використовуючи графічний інтерфейс, ви б не тільки клацали мишею на свому робочому місці декілька годин, але й могли б потенційно також внести помилку в процесі виконання монотонної задачі. Саме тут ми й скористаємося перевагами терміналу Unix. Термінал Unix - це одночасно інтерфейс командного рядка (англ. “Command-Line Interface”, CLI) та скриптова мова програмування, яка дозволяє виконувати подібні повторювані задачі автоматично та швидко. За допомогою відповідних команд термінал може повторювати задачі із певними змінами або без них стільки разів, скільки ми бажаємо. З використанням терміналу приклад задачі з бібліографічним пошуком може бути вирішений за секунди.
Термінал
Термінал - це програма, де користувач може вводити команди. За допомогою терміналу можна запускати складні програми, такі як програмне забезпечення для моделювання клімату, або прості команди, які створюють пустий каталог, командами, які займають лише один рядок. Найбільш популярним терміналом є Bash (the Bourne Again SHell, який отримав таку назву, тому що був розроблений на основі терміналу, написаного Стівеном Борном). Bash є терміналом за замовчуванням у більшості сучасних реалізацій Unix та у більшості пакетів, які надають Unix-подібні інструменти для Windows. Зауважте, що ‘Git Bash’ — це частина програмного забезпечення, яка дозволяє користувачам Windows використовувати інтерфейс, подібний до Bash, при взаємодії з Git.
Щоб користуватися терміналом, потрібно докласти певних зусиль і витратити час на його вивчення. У той час як графічний інтерфейс надає вам можливість вибору, команди терміналу не надаються автоматично, тому вам доведеться вивчити кілька команд, як нову лексику у мові, яку ви вивчаєте. Однак, на відміну від розмовної мови, невелика кількість “слів” (тобто команд) принесе вам неймовірну користь, і сьогодні ми розглянемо кілька найважливіших з них.
Граматика терміналу дозволяє комбінувати наявні інструменти у потужні конвеєри та автоматично обробляти великі обсяги даних. Послідовності команд можуть бути записані у скрипт, покращуючи відтворюваність послідовностей дій.
Крім того, командний рядок часто є найпростішим способом взаємодії з віддаленими машинами та суперкомп’ютерами. Ознайомлення з терміналом є майже необхідним для запуску різноманітних спеціалізованих інструментів і ресурсів, у тому числі надпродуктивних обчислювальних систем. Оскільки кластери та хмарні обчислювальні системи стають все більш популярними для обробки наукових даних, вміння взаємодіяти з терміналом стає необхідною навичкою. Ми можемо розвивати навички роботи з командним рядком, описані тут, для вирішення широкого спектра наукових питань і обчислювальних проблем.
Отже, почнемо.
Коли термінал тільки відкрито, вам пропонується запит (англ. prompt), яке вказує на те, що термінал очікує на введення команд.
Термінал зазвичай використовує символ $ як запрошення,
але може використовувати й інші символи. У прикладах до цього уроку ми
використовуватимемо запрошення $. Найважливіше: під час
введення команд запрошення вводити не треба. Треба вводити
тільки команди, що йдуть за ним. Це правило діє як на цих уроках, так і
на уроках з інших джерел. Також зауважте, що після введення команди, вам
потрібно натиснути клавішу Enter для її виконання.
За запрошенням йде текстовий курсор - символ, який позначає позицію, де ви будете вводити текст. Курсор зазвичай блимає або є суцільним блоком, але він також може бути підкресленням або вертикальною рискою. Ви могли його бачити, наприклад, в текстових редакторах.
Зверніть увагу, що ваше запрошення може виглядати дещо інакше. Зокрема, більшість популярних середовищ оболонки за замовчуванням вказують ваше ім’я користувача та ім’я хоста перед ‘$’. Таке запрошення може виглядати, наприклад, так:
Запрошення може містити навіть ще більше інформації. Не хвилюйтеся,
якщо ваше запрошення - це не просто коротке $. Цей урок не
залежить від цієї додаткової інформації, та вона також не повинна вам
заважати. Єдиним важливим елементом, на якому слід зосередитися, є сам
символ $, і ми побачимо пізніше, чому.
Отже, спробуймо нашу першу команду, ls (походить від
англійського слова “listing”). Ця команда покаже зміст поточного
каталогу:
ВИХІД
Desktop Downloads Movies Pictures
Documents Library Music Public
Команду не знайдено
Конвеєр Неллі: Типова Проблема
Неллі Немо (Nelle Nemo), морський біолог, щойно повернулась із
шестимісячного дослідження Північного
тихоокеанського кругообігу (North Pacific Gyre), де вона збирала
зразки драглистих морських організмів у Великій
тихоокеанській сміттєвій плямі. Вона має 1520 зразків, які вона
пропускає через аналізатор, щоб виміряти відносну кількість 300 білків.
Їй потрібно запустити ці 1520 файлів через уявну програму
goostats.sh, яку вона успадкувала. Окрім цього величезного
завдання, вона має написати результати до кінця місяця, щоб її робота
могла з’явитися у спеціальному випуску Aquatic Goo Letters.
Якщо Неллі вирішить запустити goostats.sh вручну за
допомогою графічного інтерфейсу, їй доведеться вибирати та відкривати
файли 1520 разів. Якщо обробка одного файлу програмою
goostats.sh триватиме 30 секунд, загальний процес
вимагатиме більше ніж 12 годин уваги Неллі. За допомогою терміналу,
Неллі може замість цього доручити своєму комп’ютеру цю рутинну роботу в
той час, коли вона фокусує свою увагу на написанні статті.
У наступних кількох уроках будуть розглянуті шляхи, яким чином Неллі
може цього досягти. Зокрема, на уроках пояснюється, як вона може
використовувати термінал для запуску програми goostats.sh,
використовуючи цикли для автоматизації повторюваних кроків введення імен
файлів, щоб її комп’ютер міг працювати, поки вона пише свою наукову
роботу.
Як бонус, після того, як вона створить конвеєр, вона зможе використовувати його повторно, коли вона збере більше даних.
Для того, щоб досягти своєї мети, Неллі необхідно знати, як:
- перейти до файла/каталогу
- створити файл/каталог
- перевірити довжину файлу
- з’єднати команди разом
- отримати набір файлів
- по черзі виконати дії над кожним файлом з набору
- запустити скрипт, що містить розроблений нею конвеєр
- Термінал - це програма, основним призначенням якої є читання команд і запуск інших програм.
- У цьому уроці використовується Bash. Це термінал за замовчуванням у багатьох реалізаціях Unix.
- Програми можна запускати у Bash шляхом введення команд у вікні командного рядка.
- Основними перевагами терміналу є високе співвідношення кількості дій до кількості натискань клавіш, підтримка автоматизації повторюваних завдань, а також можливість доступу до віддалених машин.
- Дуже важлива навичка при використанні оболонки - це вміння доречно використовувати текстові команди.
Content from Навігація по файловій системі
Останнє оновлення 2025-08-07 | Редагувати цю сторінку
Приблизний час: 40 хвилин
Огляд
Питання
- Як я можу пересуватися по файловій системі на моєму комп’ютері?
- Як я можу переглянути файли та каталоги на своєму комп’ютері?
- Як я можу вказати, де знаходиться файл або каталог на моєму комп’ютері?
Цілі
- Пояснити подібності та відмінності між файлом і каталогом.
- Перетворити абсолютний шлях у відносний і навпаки.
- Створити абсолютні та відносні шляхи, які ідентифікують певні файли та каталоги.
- Використати опції та аргументи для зміни поведінки команд у терміналі.
- Продемонструвати використання табуляції для автоматичного доповнення та пояснити його переваги.
Ознайомлення та навігація з файловою системою у терміналі (про яку йдеться у розділі Навігація файлами та каталогами) можуть бути складними. Ви можете відкрити термінал та графічний провідник файлів поруч, щоб учні могли бачити вміст і структуру файлів, коли вони використовують термінал для навігації системою.
Частина операційної системи, яка відповідає за роботу з файлами та каталогами, називається файловою системою. Вона організує наші дані у файли, які зберігають інформацію, та каталоги (також відомі як ‘теки’), які містять файли або інші підкаталоги.
Для створення, перевірки, перейменування та видалення файлів і каталогів зазвичай використовується декілька команд. Щоб розглянути їх, перейдемо до нашого відкритого вікна терміналу.
По-перше, дізнаймося, де ми знаходимося, запустивши команду
pwd (англ. ‘print working directory’ - надрукувати робочий
каталог). Каталоги подібні до місцезнаходження - у будь-який
момент, коли ми використовуємо термінал, ми знаходимося в одному місці,
яке називається поточним робочим каталогом. Команди
здебільшого читають та записують файли в поточний робочий каталог, тобто
“сюди”. Тому дуже важливо розуміти де ви знаходитесь перед виконанням
команди. Команда pwd покаже вам, де ви знаходитесь:
ВИХІД
/Users/nelle
У наведеному прикладі комп’ютер відповів /Users/nelle,
що є домашнім каталогом Неллі:
Варіації домашнього каталогу
Розташування домашнього каталогу виглядає по-різному в різних
операційних системах. В Linux воно може виглядати як
/home/nelle, а у Windows воно буде схоже на
C:\Documents and Settings\nelle чи
C:\Users\nelle. (Зауважте, що воно може виглядати дещо
інакше для різних версій Windows.) У наведених нижче прикладах ми
використовували результати у тому вигляді, у якому вони виглядають у
macOS. Хоча вихідні дані Linux і Windows можуть дещо відрізнятися,
загалом вони мають бути схожими.
Ми також припустимо, що ваша команда pwd повертає вашу
домашню директорію користувача. Якщо команда pwd повертає
щось інше, вам доведеться перейти у ваш домашній каталог за допомогою
команди cd, інакше деякі команди в цьому уроці не будуть
працювати належним чином. Дивіться Перегляд інших каталогів для
додаткової інформації про команду cd.
Для того, щоб зрозуміти, що таке ‘домашній каталог’, розглянемо як організована файлова система в цілому. Для цього прикладу ми проілюструємо файлову систему на комп’ютері морського біолога Неллі. Після цього прикладу ви вивчатимете команди для дослідження власної файлової системи, яка буде побудована подібним чином, але не буде абсолютно ідентичною.
На комп’ютері Неллі файлова система виглядає так:
Файлова система виглядає як перевернуте дерево. Найвищим каталогом є
кореневий каталог, який містить усе інше. Ми
посилаємося на нього за допомогою символу скісної риски /
(зауважте, що він є першим символом у рядку
/Users/nelle).
Усередині цього каталогу є кілька інших каталогів: bin
(в якому зберігаються певні вбудовані програми), data (для
різноманітних файлів даних), Users (де знаходяться особисті
директорії користувачів), tmp (для файлів тимчасового
зберігання) та інші.
Ми знаємо, що наш поточний робочий каталог /Users/nelle
зберігається всередині каталогу /Users, тому що
/Users є першою частиною його імені. Відповідно, нам
відомо, що каталог /Users зберігається всередині кореневої
директорії /, бо його ім’я розпочинається з символу
/.
Символи скісної риски
Зверніть увагу, що символ / має два значення. Коли він
з’являється на початку назви файлу чи каталогу, це посилання на кореневу
директорію. Коли він використовується всередині шляху, це лише
роздільник.
На комп’ютері Неллі, у каталозі /Users є підкаталог для
кожного користувача з обліковим записом, наприклад: для її колег
imhotep та larry.
Файли користувача imhotep зберігаються в каталозі
/Users/imhotep, користувача larry - в
/Users/larry, і Неллі - в /Users/nelle.
Оскільки саме Неллі є користувачем у наших прикладах, тому ми отримуємо
/Users/nelle як наш домашній каталог. Зазвичай, коли ви
відкриваєте нове вікно терміналу, ви опиняєтесь у своєму домашньому
каталозі.
Тепер розглянемо команду, яка дозволить нам бачити вміст нашої
власної файлової системи. Ми можемо побачити, що знаходиться у нашому
домашньому каталозі, запустивши ls:
ВИХІД
Applications Documents Library Music Public
Desktop Downloads Movies Pictures
(Знову ж таки, ваші результати можуть дещо відрізнятися залежно від вашої операційної системи та того, як ви налаштували свою файлову систему.)
ls друкує назви файлів і каталогів у поточному каталозі.
Ми можемо зробити його вивід більш зрозумілим за допомогою
опції -F, яка вказує ls
класифікувати вивід, додаючи маркер до імен файлів і каталогів, щоб
вказати, що вони собою являють:
- символ
/наприкінці імені вказує на те, що це каталог - символ
@вказує на посилання - символ
*вказує на виконуваний файл
Залежно від налаштувань терміналу за замовчуванням, він також може використовувати кольори для позначення файлів та каталогів, щоб краще їх розрізняти.
ВИХІД
Applications/ Documents/ Library/ Music/ Public/
Desktop/ Downloads/ Movies/ Pictures/
В наведеному прикладі ми бачимо, що наш домашній каталог містить лише підкаталоги. Будь-які імена у вихідних даних, які не мають символу класифікації, є файлами, розташованими в поточному робочому каталозі.
Як очистити термінал
Якщо екран стає занадто захаращеним, ви можете очистити термінал за
допомогою команди clear. Ви все ще можете отримати доступ
до попередніх команд за допомогою клавіш ↑ та ↓
для переміщення по рядках, або за допомогою прокрутки у вашому
терміналі.
Отримання допомоги
У ls є багато інших опцій. Існує два поширених способи
дізнатися, як використовувати команду і які параметри вона приймає —
залежно від вашого середовища, ви можете виявити, що працює лише
один із цих способів:
- Ми можемо передати команді опцію
--help(доступну в Linux і Git Bash), наприклад:
- Ми можемо переглянути інструкцію до використання команди за
допомогою
man(доступної на Linux і macOS), наприклад:
Далі ми роздивимось обидва способи.
Довідка для вбудованих команд
Деякі команди вбудовано в оболонку Bash, а не існують як окремі
програми у файловій системі. Одним із прикладів є команда
cd (зміна каталогу). Якщо після команди man cd
ви отримуєте повідомлення на кшталт No manual entry for cd,
спробуйте натомість help cd. За допомогою команди
help ви можете отримати інформацію про використання вбудованих
команд Bash.
Опція `–help’
Більшість команд bash і програм, написаних людьми для запуску з bash,
підтримують опцію --help, яка виводить додаткову інформацію
про те, як користуватися відповідною командою або програмою.
ВИХІД
Usage: ls [OPTION]... [FILE]...
List information about the FILEs (the current directory by default).
Sort entries alphabetically if neither -cftuvSUX nor --sort is specified.
Mandatory arguments to long options are mandatory for short options, too.
-a, --all do not ignore entries starting with .
-A, --almost-all do not list implied . and ..
--author with -l, print the author of each file
-b, --escape print C-style escapes for nongraphic characters
--block-size=SIZE scale sizes by SIZE before printing them; e.g.,
'--block-size=M' prints sizes in units of
1,048,576 bytes; see SIZE format below
-B, --ignore-backups do not list implied entries ending with ~
-c with -lt: sort by, and show, ctime (time of last
modification of file status information);
with -l: show ctime and sort by name;
otherwise: sort by ctime, newest first
-C list entries by columns
--color[=WHEN] colorize the output; WHEN can be 'always' (default
if omitted), 'auto', or 'never'; more info below
-d, --directory list directories themselves, not their contents
-D, --dired generate output designed for Emacs' dired mode
-f do not sort, enable -aU, disable -ls --color
-F, --classify append indicator (one of */=>@|) to entries
... ... ...
Коли використовувати короткі або довгі опції
Коли існують як короткі, так і довгі опції:
- Використовуйте коротку під час введення команд безпосередньо в термінал, щоб мінімізувати натискання клавіш і швидше виконувати завдання.
- Використовуйте довгу опцію у скриптах для наочності. Вона буде надрукована лише один раз, але прочитана багато разів.
Команда man
Інший спосіб дізнатися про ls - ввести
Ця команда виведе у вашому терміналі сторінку з описом команди
ls та її опцій.
Для навігації сторінками man ви можете використовувати
↑ і ↓ для переміщення по рядках, або спробувати
b і Spacebar для переходу вгору і вниз на цілу
сторінку. Для пошуку символу або слова на сторінках man,
використовуйте клавішу / та слідом введіть символ або слово,
яке ви шукаєте. Іноді пошук може призвести до кількох результатів. У
такому випадку ви можете переміщатися між результатами за допомогою
клавіш N (для переходу вперед) та
Shift+N (для переходу назад).
Щоб вийти зі сторінок man, натисніть
q.
Сторінки з інструкціями в Інтернеті
Звісно, є й третій спосіб отримати доступ до довідки для команд:
пошук в інтернеті за допомогою веббраузера. Якщо ви скористаєтеся
пошуком в Інтернеті, додання до запиту фрази unix man page
дозволить отримати більш доречні результати.
GNU надає посилання на свої посібники, зокрема на основні утиліти GNU, які охоплюють багато команд, представлених у цьому уроці.
Вивчення інших опцій ls
Ви також можете використовувати декілька опцій одночасно. Що робить
команда ls при використанні з опцією -l? А
якщо ви використовуєте -l та -h одночасно?
Деякі з результатів виконання команди стосуються властивостей, які ми не розглядаємо у цьому семінарі (наприклад, права доступу до файлів та їх власники), але решта все одно буде корисною.
Опція -l змушує ls використовувати довгий
(англ. long) формат виводу, показуючи не лише назви
файлів/директорій, але й додаткову інформацію, таку як розмір файлу і
час його останньої модифікації. Якщо ви використовуєте як
-h, так і -l, це зробить виведення розміру
файлу у більш зрозумілому людині вигляді (“human
readable”), тобто покаже щось на кшталт 5.3K замість
5369.
Виведення у зворотному хронологічному порядку
За замовчуванням ls виводить вміст каталогу в
алфавітному порядку за іменами елементів. Команда ls -t
перелічує елементи за часом останньої зміни, а не за алфавітом. Команда
ls -r виводить вміст каталогу у зворотному порядку. Який
файл буде показано останнім при комбінації опцій -t і
-r? Підказка: Вам потрібно скористатися опцією
-l, щоб переглянути дати останніх змін.
При використанні -rt останній змінений файл є останнім у
списку. Це може бути дуже корисним для пошуку ваших останніх редагувань
або перевірки чи було створено новий вихідний файл.
Перегляд інших каталогів
Ми можемо використовувати ls не лише у поточному
робочому каталозі, але й для виведення вмісту іншого каталогу.
Подивимося на наш каталог Desktop (робочий стіл), виконавши
ls -F Desktop, тобто, команду ls з
опцією -F і аргументом
Desktop. Аргумент Desktop повідомляє
ls, що ми хочемо отримати список чогось іншого, ніж наш
поточний робочий каталог:
ВИХІД
shell-lesson-data/
Зауважте, що якщо у вашому поточному робочому каталозі не існує
каталогу з назвою Desktop, ця команда поверне помилку.
Зазвичай, підкаталог Desktop існує у вашому домашньому
каталозі, який ми вважаємо поточним робочим каталогом вашого терміналу
bash.
На виході ви маєте отримати список усіх файлів і підкаталогів у
вашому каталозі Desktop, включно з каталогом
shell-lesson-data, який ви завантажили за посиланням під
час налаштувань для цього уроку. (На більшості
систем вміст каталогу Desktop в терміналі можна побачити на
екрані у вигляді піктограм, якщо згорнути або закрити усі вікна у
графічному інтерфейсі користувача. Подивіться, чи це ваш випадок.)
Ієрархічна організація речей таким чином допомагає нам відстежувати нашу роботу. Хоча у нашому домашньому каталозі можна зберігати сотні файлів, так само як і сотні паперових документів на робочому столі, набагато легше знаходити речі, коли вони організовані у підкаталоги з розумними назвами.
Тепер, коли ми знаємо, що каталог shell-lesson-data
знаходиться у каталозі Desktop, ми можемо зробити дві речі.
По-перше, ми можемо переглянути його вміст, використовуючи ту ж
стратегію, що і раніше, передавши ім’я каталогу в ls:
ВИХІД
exercise-data/ north-pacific-gyre/
По-друге, ми можемо змінити наше місцезнаходження на інший каталог, щоб ми більше не знаходилися в нашому домашньому каталозі.
Командою для зміни каталогів є cd, після якої йде назва
каталогу, до якого ви хочете перейти. Це оновить поточний робочий
каталог. cd означає ‘змінити каталог’ (англ. ‘change
directory’), що трохи вводить в оману. Команда не змінює сам каталог;
вона змінює поточний робочий каталог у терміналі. Іншими словами, вона
змінює налаштування терміналу щодо того, в якому каталозі ми
знаходимося. Команда cd подібна до подвійного клацання по
каталогу в графічному інтерфейсі, щоб потрапити до нього.
Припустимо, нам треба перейти до каталогу exercise-data,
який ми бачили вище. Ми можемо скористатися наступною серією команд, щоб
дістатися туди:
Ці команди перемістять нас з домашнього каталогу до Desktop, потім до
shell-lesson-data, а потім до exercise-data.
Ви помітите, що команда cd нічого не виводить. Це
нормально. Багато команд терміналу нічого не виводять на екран після
успішного виконання. Але якщо ми виконаємо pwd після неї,
то побачимо, що зараз ми знаходимося у
/Users/nelle/Desktop/shell-lesson-data/exercise-data.
Тепер, якщо ми виконаємо команду ls -F без аргументів,
вона виведе вміст
/Users/nelle/Desktop/shell-lesson-data/exercise-data, тому
що саме там ми зараз знаходимося:
ВИХІД
/Users/nelle/Desktop/shell-lesson-data/exercise-data
ВИХІД
alkanes/ animal-counts/ creatures/ numbers.txt writing/
Тепер ми знаємо, як рухатися вниз по дереву каталогів (тобто, як перейти до підкаталогу), але як рухатися вгору (тобто, як вийти з каталогу і перейти до його батьківського каталогу)? Ми можемо спробувати наступне:
ПОМИЛКА
-bash: cd: shell-lesson-data: No such file or directory
Але ми отримуємо помилку! Чому?
За допомогою поки що знайомих нам методів, cd може
бачити лише підкаталоги у вашому поточному каталозі. Існують різні
способи перегляду батьківських каталогів; ми почнемо з
найпростішого.
У терміналі є скорочення для переходу на один рівень каталогу вгору. Це працює наступним чином:
.. - це спеціальне ім’я каталогу, що означає “каталог,
що містить поточний”, або більш стисло, батько
поточного каталогу. Звичайно, якщо ми запустимо pwd після
виконання cd .., ми знову у
/Users/nelle/Desktop/shell-lesson-data:
ВИХІД
/Users/nelle/Desktop/shell-lesson-data
Спеціальний каталог .. зазвичай не з’являється, коли ми
запускаємо ls. Якщо ми хочемо побачити його, ми можемо
додати опцію -a до ls -F:
ВИХІД
./ ../ exercise-data/ north-pacific-gyre/
-a означає ‘показати все’ (англ. show all) (включно з
прихованими файлами); ця опція змушує ls показувати нам
імена файлів і каталогів, які починаються з ., наприклад,
.. (яке, якщо ми знаходимося у /Users/nelle,
вказує на каталог /Users). Як ви можете бачити, команда
також показує ще один спеціальний каталог, який називається
., що означає ‘поточний робочий каталог’. Може здатися, що
це дещо надлишково - мати для нього ім’я, але незабаром ми побачимо, як
воно може бути використано.
Зауважте, що у більшості інструментів командного рядка можна
комбінувати декілька параметрів за допомогою одного - і без
пробілів між параметрами: ls -F -a є еквівалентним до
ls -Fa.
Інші приховані файли
Крім прихованих каталогів .. та ., ви також
можете побачити файл з назвою .bash_profile. Цей файл
зазвичай містить конфігурацію терміналу. Ви також можете зустріти інші
файли й каталоги, які починаються з символу .. Зазвичай це
конфігураційні файли та каталоги, які використовуються різними
програмами на вашому комп’ютері для налаштування. Префікс .
використовується для того, щоб ці конфігураційні файли не захаращували
термінал, коли використовується стандартна команда ls.
Ці три команди є основними командами для навігації по файловій
системі на вашому комп’ютері: pwd, ls і
cd. Розгляньмо деякі варіації цих команд. Що станеться якщо
ви введете команду cd саму по собі, не зазначаючи
каталог?
Як перевірити, що сталося? Команда pwd дає нам
відповідь!
ВИХІД
/Users/nelle
Виявляється, cd без аргументу поверне вас до домашнього
каталогу, що дуже зручно, якщо ви загубилися у власній файловій
системі.
Спробуємо повернутися до каталогу exercise-data.
Минулого разу ми використовували три команди, але насправді ми можемо
поєднати перелік каталогів для переходу до каталогу
exercise-data за один крок:
Переконайтеся, що ми перемістилися в потрібне місце, виконавши
pwd і ls -F.
Щоб перейти на один рівень вище від каталогу даних, ми можемо
використати cd ... Але існує інший спосіб переміщення до
будь-якого каталогу, незалежно від вашого поточного розташування.
Дотепер, ми використовували відносні шляхи для вказування назви каталогів або навіть шляхів до каталогів (як описано вище). Він повідомляє таким командам, як ls або cd, знайти каталог на основі нашої поточної позиції у файловій системі, а не з кореня файлової системи.
Однак ми також можемо використовувати абсолютні
шляхи, які вказують повне розташування каталогу, починаючи від
кореневого каталогу, який позначається символом скісної риски (/).
Символ / на початку абсолютного шляху вказує комп’ютеру
слідувати шляхом від кореня файлової системи, тому шлях інтерпретується
однаково, незалежно від нашого поточного каталогу.
Це дає змогу перейти до каталогу shell-lesson-data з
будь-якого місця у файловій системі (у тому числі з каталогу
exercise-data). Щоб знайти абсолютний шлях ми можемо
скористатися pwd, а потім витягти потрібний нам фрагмент,
щоб перейти до shell-lesson-data.
ВИХІД
/Users/nelle/Desktop/shell-lesson-data/exercise-data
Виконайте pwd і ls -F, щоб переконатися, що
ми знаходимося в потрібному каталозі.
Ще два скорочення
Термінал інтерпретує символ тильди (~) на початку шляху
як “домашній каталог поточного користувача”. Наприклад, якщо домашнім
каталогом користувача Неллі є каталог /Users/nelle, то
~/data еквівалентно /Users/nelle/data. Це
працює лише у випадку, якщо це перший символ у шляху:
here/there/~/elsewhere не
єhere/there/Users/nelle/elsewhere.
Іншим скороченням є символ - (тире). cd
інтерпретує - як попередній каталог, у якому я
був, що є швидше, ніж запам’ятовувати, а потім набирати повний
шлях. Це дуже ефективний спосіб переміщення між двома
каталогами - тобто, якщо ви виконаєте cd - двічі, це
повертає вас до початкового каталогу.
Різниця між cd .. і cd - полягає в тому, що
перший переміщується на один рівень вище в ієрархії каталогів,
а другий повертає вас назад.
Спробуйте! Спочатку перейдіть до
~/Desktop/shell-lesson-data (ви вже маєте бути там).
Потім cd у каталог
exercise-data/creatures
Тепер, якщо ви виконаєте
ви побачите, що повернулися до
~/Desktop/shell-lesson-data. Запустіть cd - ще
раз і ви повернетесь до
~/Desktop/shell-lesson-data/exercise-data/creatures
Абсолютні та відносні шляхи
Якщо Неллі зараз знаходиться в /Users/nelle/data, то яка
з наведених нижче команд дозволить їй повернутися до її домашнього
каталогу /Users/nelle?
cd .cd /cd /home/nellecd ../..cd ~cd homecd ~/data/..cdcd ..
Ні: скорочення
.означає поточний каталог.Ні: скорочення
/означає кореневий каталог.Ні: домашнім каталогом Неллі є
/Users/nelle.Ні: ця команда переходить на два рівні вгору, тобто до
/Users.Так: символ
~позначає домашній каталог користувача, у цьому випадку/Users/nelle.Ні: ця команда виконає перехід до каталогу
homeу поточному каталозі, якщо він існує.Так: надмірно складна, але правильна.
Так: скорочення для повернення до домашнього каталогу користувача.
Так: підіймається на один рівень вище в структурі каталогів.
Завдання відносного шляху
Використовуючи наведену нижче схему файлової системи, якщо
pwd показує /Users/thing, що покаже команда
ls -F ../backup?
../backup: No such file or directory (не існує такого файлу або каталогу)2012-12-01 2013-01-08 2013-01-272012-12-01/ 2013-01-08/ 2013-01-27/original/ pnas_final/ pnas_sub/
Ні: у каталозі
/Usersіснує підкаталогbackup.Ні: це вміст каталогу
Users/thing/backup, але за допомогою..ми просили піднятися на один рівень вище.Ні: див. попереднє пояснення.
Так:
../backup/вказує на/Users/backup/.
Розуміння команди ls
Звертаючись до діаграми файлової системи нижче, якщо pwd
повертає /Users/backup, а параметр -r у
команді ls змінює порядок виведення результатів, яка (які)
команда (команди) призведе до наступного результату:
ВИХІД
pnas_sub/ pnas_final/ original/
ls pwdls -r -Fls -r -F /Users/backup
Ні:
pwdне є назвою каталогу.Так: команда
lsбез аргументу перелічує файли й каталоги у поточному каталозі.Так: чітко використовує абсолютний шлях.
Загальний синтаксис команд терміналу
Ми вже познайомилися з командами, опціями та аргументами, але, можливо, буде корисно формалізувати деяку термінологію.
Розглянемо команду нижче як приклад і розберемо її на складові частини:
ls - це команда, з
опцією -F та аргументом
/. Ми вже зустрічалися з опціями, які починаються з одного
тире (-), відомі як короткі варіанти, або
двох тире (--), відомі як довгі варіанти.
[Опції] змінюють поведінку команди, а [аргументи] вказують команді, над
чим вона має працювати (наприклад, над файлами й каталогами). Іноді
опції та аргументи називають параметрами. Команда може
сприймати кілька параметрів і аргументів, але вона не завжди вимагає
їх.
Опції також іноді називають перемикачами або прапорцями, особливо якщо вони не приймають аргументів. У цьому уроці ми будемо дотримуватися терміну опція.
Кожна частина відокремлюється пробілами. Якщо ви пропустите пробіл
між ls і -F, термінал шукатиме команду з
назвою ls-F, якої не існує. Також, параметри чутливі до
регістру. Наприклад, ls -s покаже розміри файлів та
каталогів поряд з їхніми назвами., а ls -S відсортує файли
та каталоги за розміром, як показано нижче:
ВИХІД
total 28
4 animal-counts 4 creatures 12 numbers.txt 4 alkanes 4 writing
Зверніть увагу, що розміри, які повертає команда ls -s,
подано у блоках. Оскільки вони визначаються по-різному для
різних операційних систем, ви можете отримати не такі значення, як у
прикладі.
ВИХІД
animal-counts creatures alkanes writing numbers.txt
Зібравши все це разом, команда ls -F / вище дасть нам
список файлів і каталогів у кореневому каталозі /. Нижче
наведено приклад результату, який ви можете отримати від цієї
команди:
ВИХІД
Applications/ System/
Library/ Users/
Network/ Volumes/
Конвеєр Неллі: Організація файлів
Знаючи так багато про файли та каталоги, Неллі готова впорядкувати файли, які створить машина для аналізу білків.
Вона створює каталог під назвою north-pacific-gyre (щоб
нагадати собі, звідки взялися дані), який міститиме файли даних з
аналітичної машини та її скрипти для обробки даних.
Кожному фізичному зразку присвоюється унікальний десятисимвольний
ідентифікатор, наприклад ‘NENE01729A’, згідно з затвердженими в
лабораторії правилами. Оскільки цей ідентифікатор вона використовує у
своєму журналі для документування таких деталей, як місцезнаходження,
часу і глибини, то вона додає його до імен своїх файлів даних. Оскільки
результат роботи аналізатора є звичайним текстом, вона назве свої файли
NENE01729A.txt, NENE01812A.txt і так далі. Усі
1520 файлів буде збережено в одному каталозі.
Тепер у її поточному каталозі shell-lesson-data, Неллі
може побачити, які файли вона має за допомогою цієї команди:
Ця команда вимагає багато друку, але Неллі може мінімізувати зусилля, використовуючи табуляцію, що дозволяє терміналу автоматично завершувати команди та імена файлів. Якщо вона набере:
а потім натисне клавішу Tab (клавішу табуляції на її клавіатурі), то термінал автоматично доповнить назву каталогу для неї:
Повторне натискання клавіші Tab нічого не дасть, оскільки існує декілька варіантів; якщо натиснути Tab двічі, буде показано список усіх відповідних файлів.
Якщо Неллі потім натисне щеG і знову Tab, оболонка додасть ‘goo’, оскільки всі файли, що починаються з ‘g’, мають спільні перші три символи ‘goo’.
Щоб побачити всі ці файли, вона може натиснути клавішу Tab ще двічі.
Ця функція відома як автодоповнення табуляцією, і ми зустрінемо її у багатьох інших інструментах протягом цього уроку.
- Файлова система відповідає за керування інформацією на диску.
- Інформація зберігається у файлах, які зберігаються в каталогах (теках).
- Каталоги також можуть зберігати інші підкаталоги, які таким чином створюють дерево каталогів.
- Команда
pwdвиводить поточний робочий каталог користувача. - Команда
ls [path]виводить список з певного файлу або каталогу; командаlsсама по собі виводить список поточного робочого каталогу. - Команда
cd [path]змінює поточний робочий каталог. - Більшість команд приймають параметри, які починаються з одного
символу
-. - Назви каталогів в шляху розділяються символами
/в Unix, але\в Windows. - Символ
/сам по собі зазначає кореневий каталог усієї файлової системи. - Абсолютний шлях вказує на розташування відносно кореня файлової системи.
- Відносний шлях вказує на розташування, починаючи з поточного каталогу.
- Символ
.сам по собі означає ‘поточний каталог’;..означає ‘батьківський каталог’ (той, що знаходиться над поточним каталогом).
Content from Робота з файлами та каталогами
Останнє оновлення 2025-08-28 | Редагувати цю сторінку
Приблизний час: 50 хвилин
Огляд
Питання
- Як я можу створювати, копіювати та видаляти файли і каталоги?
- Як я можу редагувати файли?
Цілі
- Створити ієрархію каталогів, яка відповідає заданій схемі.
- Створити файли в цій ієрархії за допомогою редактора або шляхом копіювання та перейменування файлів, що вже існують.
- Видалити, скопіювати та перемістити вказані файли та/або каталоги.
Створення каталогів
Тепер ми знаємо, як досліджувати файли та каталоги, але як їх створювати?
У цьому уроці ми дізнаємося про створення та переміщення файлів і
каталогів на прикладі каталогу exercise-data/writing.
Крок перший: подивимось, де ми знаходимося і що вже маємо
Ми все ще маємо бути у каталозі shell-lesson-data на
Робочому столі (англ. Desktop), що ми можемо перевірити за
допомогою:
ВИХІД
/Users/nelle/Desktop/shell-lesson-data
Далі ми перейдемо до каталогу exercise-data/writing і
подивимося, що у ньому міститься:
ВИХІД
haiku.txt LittleWomen.txt
Створення каталогу
Створимо новий каталог з назвою thesis за допомогою
команди mkdir thesis (яка не має виводу):
Як ви можете здогадатися з її назви, команда mkdir
означає ‘створити каталог’ (англ. ‘make directory’). Оскільки
thesis є відносним шляхом (тобто не має початкової косої
риски, як /what/ever/thesis), новий каталог буде створено у
поточному робочому каталозі:
ВИХІД
haiku.txt LittleWomen.txt thesis/
Оскільки ми щойно створили каталог thesis, у ньому ще
нічого немає:
Зауважте, що команда mkdir не тільки створює окремі
каталоги по одному за раз. Параметр -p дозволяє команді
mkdir створювати каталог із вкладеними підкаталогами за
одну операцію:
Параметр -R з командою ls покаже усі
вкладені підкаталоги у каталозі. Скористаймось ls -FR для
рекурсивного зображення нової ієрархії каталогів, яку ми щойно створили
у каталозі project:
ВИХІД
../project/:
data/ results/
../project/data:
../project/results:
Два способи зробити одне й те саме
Використання терміналу для створення каталогу нічим не відрізняється
від використання файлового провідника. Якщо ви зараз відкриєте поточний
каталог за допомогою графічного провідника файлів вашої операційної
системи, там також з’явиться каталог thesis. Хоча термінал
і файловий провідник - це два різні способи взаємодії з файлами, самі
файли й каталоги одні й ті ж самі.
Доречні імена для файлів і каталогів
Використання надто складних імен для файлів і каталогів може ускладнити роботу в командному рядку. Ось кілька корисних порад щодо вибору ефективних імен.
- Не використовуйте пробіли.
Пробіли можуть зробити назву більш змістовною, але оскільки вони
використовуються для відокремлення аргументів у командному рядку, краще
уникати їх у назвах файлів і каталогів. Ви можете використовувати
- або _ (наприклад,
north-pacific-gyre/ замість
north pacific gyre/). Щоб перевірити це, спробуйте набрати
mkdir north pacific gyre і подивіться, який каталог (або
каталоги!) буде створено, перевірив це за допомогою
ls -F.
- Не починайте назву з
-(тире).
Команди розглядають назви, що починаються з -, як
опції.
- Використовуйте літери, цифри,
.(крапку),-(тире) і_(підкреслення).
Багато інших символів мають особливе значення у командному рядку. Деякі з них ми розглянемо у цьому уроці. Існують спеціальні символи, які можуть спричинити неправильну роботу команди й навіть призвести до втрати даних.
Якщо вам потрібно звернутися до назв файлів або каталогів, які
містять пробіли чи інші спеціальні символи, вам слід узяти назву в
одинарні лапки
('').
Початківці іноді не знають, як вийти з таких редакторів, як Vim, Emacs чи Nano. Закриття терміналу та відкриття нового вікна може бути незручним, оскільки учням доведеться знову переходити до потрібного каталогу. Для пом’якшення цієї проблеми ми радимо викладачам використовувати той самий текстовий редактор, що й учні під час семінарів (у більшості випадків Nano).
Створення текстового файлу
Перейдімо до каталогу thesis за допомогою
cd, а потім запустимо текстовий редактор Nano та створимо
файл з назвою draft.txt:
Який редактор використовувати?
Коли ми говоримо, що ‘nano - це текстовий редактор’, ми
дійсно маємо на увазі ‘текстовий’. У ньому неможливо переглядати або
редагувати таблиці, зображення чи будь-які інші зручні для сприйняття
людиною дані. Ми використовуємо його у прикладах, оскільки це один із
найпростіших текстових редакторів. Однак, через це він може виявитися
недостатньо потужним або гнучким для складніших завдань, які вам
потрібно буде виконати після завершення цього семінару. У системах Unix
(таких як Linux та macOS), багато програмістів використовують [Emacs]
(https://www.gnu.org/software/emacs/) чи Vim (обидва вимагають більше часу на
вивчення), або графічний редактор, такий як Gedit чи VScode. У Windows, можливо, ви
захочете скористатися Notepad++. Операційна система
Windows також має вбудований редактор з назвою notepad,
який можна запустити з командного рядка так само, як і nano
для цього семінару.
Незалежно від того, яким редактором ви користуєтеся, вам потрібно знати, де він шукає і зберігає файли. Якщо ви запускаєте його з термінала, він (імовірно) використовуватиме ваш поточний робочий каталог як розташування за замовчуванням. Однак, якщо ви використовуєте меню “Пуск” вашого комп’ютера, файли за замовчуванням можуть зберігатися замість цього на робочому столі або в каталозі “Документи” (Documents). Ви можете змінити це, перейшовши до іншого каталогу під час першого виконання команди “Зберегти як…” (“Save As…”).
Наберемо кілька рядків тексту.
{alt=“Скриншот текстового
редактора nano в дії з текстом”У минулому це було - публікуй чи зникни,
а наразі стало - ділися та процвітай”}
Як тільки ми будемо задоволені нашим текстом, нам треба використати
комбінацію Ctrl+O (утримуючи клавішу
Ctrl or Control, натисніть клавішу O),
щоб зберегти наші дані на диск. Потім нам буде запропоновано вказати
ім’я файлу, у якому зберігатиметься наш текст. Натисніть
Return, щоб прийняти запропоновану за замовчуванням назву
draft.txt.
Як тільки файл було збережено, скористаємось комбінацією клавіш Ctrl+X, щоб вийти з редактора і повернутися до термінала.
Клавіша Control, Ctrl або ^
Клавіші Control також називається клавішею ‘Ctrl’. Існує декілька способів, якими може бути описане використання клавіші Control. Наприклад, ви можете побачити вказівку натиснути клавішу Control і, утримуючи її натиснутою, потім натиснути клавішу X, описану будь-яким з наступних способів:
Control-XControl+XCtrl-XCtrl+X^XC-x
У nano, у нижній частині екрана ви побачите
^G Get Help ^O WriteOut. Це означає, що ви можете
скористатися Control-G для отримання довідки й
Control-O для збереження вашого файлу.
Після завершення роботи команда nano не залишає жодних
даних на екрані, але ls тепер показує, що ми створили файл
з назвою draft.txt:
ВИХІД
draft.txt
Створення файлів іншим способом
Ми побачили, як створювати текстові файли за допомогою редактора
nano. Тепер спробуйте виконати наступну команду:
Що зробила команда
touch? Якщо ви відкриєте поточний каталог у файловому провіднику, чи видно в ньому цей файл?Скористуйтеся
ls -lдля перегляду файлів. Який розмір має файлmy_file.txt?У яких випадках доцільно створювати файл саме таким чином?
Команда
touchстворює новий файл з назвоюmy_file.txtу вашому поточному каталозі. Щоб переконатися, що файл створено, скористайтеся командоюls. Файлmy_file.txtтакож можна переглянути у вашому графічному провіднику файлів.Коли ви перевіряєте файл за допомогою
ls -l, зверніть увагу, що розмірmy_file.txt— 0 байт. Це означає, що файл порожній. Якщо відкрити його в редакторі, ви не знайдете в ньому жодного вмісту.Іноді програми не генерують вихідні файли автоматично, а потребують, щоб порожні файли були створені заздалегідь. Потім під час виконання програма шукає наявний файл, щоб заповнити його своїми даними. За допомогою команди
touchможна ефективно створити порожній текстовий файл для подальшого використання такими програмами.
Що ховається в імені?
Ви, мабуть, помітили, що всі файли Неллі називаються ‘щось крапка
щось’, і у цій частині уроку ми завжди використовували розширення
.txt. Це лише умовність: ми можемо назвати файл
mythesis або майже як завгодно. Однак, більшість людей
здебільшого використовують назви, що складаються з двох частин для того,
щоб допомогти їм (і їхнім програмам) розрізняти різні типи файлів. Друга
частина такого імені називається розширенням файлу і вказує тип даних у
файлі: .txt вказує на простий текстовий файл,
.pdf вказує на PDF-документ, .cfg - це
конфігураційний файл з параметрами для тієї чи іншої програми,
.png - зображення у форматі PNG, і так далі.
Це лише умовність, хоча й важлива. Файли містять лише байти: це ми та наші програми будемо їх відповідно інтерпретувати — як текст, PDF-документи, конфігураційні файли, зображення тощо.
Якщо ви назвете зображення кита у форматі PNG як
whale.mp3, це не перетворить його якимось чарівним чином на
запис пісні кита, хоча це може змусити операційну систему
спробувати відкрити його за допомогою музичного плеєра. У цьому випадку,
якщо хтось двічі клацне на файлі whale.mp3 у файловому
провіднику, музичний програвач автоматично (і помилково) спробує
відкрити файл whale.mp3.
Переміщення файлів і каталогів
Повернемося до каталогу
shell-lesson-data/exercise-data/writing:
У нашому каталозі thesis є файл draft.txt,
з не надто інформативною назвою, тому змінімо назву файлу за допомогою
команди mv, що є скороченням від ‘move’ (з англ. -
‘переміщати’):
Перший аргумент говорить mv, що ми “переміщаємо”, а
другий - куди саме. У цьому випадку ми переміщуємо
thesis/draft.txt до thesis/quotes.txt, що має
той самий ефект, що і перейменування файлу. Після цього ls
підтверджує, що thesis тепер містить один файл з назвою
quotes.txt:
ВИХІД
quotes.txt
Слід бути обережним, вказуючи ім’я цільового файлу, оскільки
mv приховано перезапише будь-який наявний файл з такою
самою назвою, а це може призвести до втрати даних. За замовчуванням
mv не запитуватиме підтвердження перед перезаписом файлів.
Однак додатковий параметр mv -i (або
mv --interactive) змусить mv запросити таке
підтвердження.
Зверніть увагу, що mv також працює з каталогами.
Перемістимо quotes.txt до поточного робочого каталогу.
Знову скористаємося mv, але цього разу ми використаємо лише
назву каталогу як другий аргумент щоб повідомити mv, що ми
хочемо зберегти назву файлу, але перемістити файл у нове місце. (Ось
чому команда називається ‘перемістити’.) У цьому випадку ми
використовуємо спеціальну назву . поточного каталогу, про
яку ми згадували раніше.
Наслідком цього буде переміщення файлу з початкового каталогу до
поточного робочого каталогу. Тепер ls показує нам, що
каталог thesis` порожній:
ВИХІД
$
Крім того, ми можемо переконатися, що файл quotes.txt
більше не присутній у каталозі thesis, спробувавши показати
інформацію про нього:
ПОМИЛКА
ls: cannot access 'thesis/quotes.txt': No such file or directory
Команда ls, якщо вказати ім’я файлу або каталогу як
аргумент, виводить лише список запитуваних файлів або каталогів. Якщо
вказаного файлу не існує, термінал поверне помилку — як ми вже бачили
раніше. Таким чином ми можемо перевірити, що файл
quotes.txt тепер знаходиться у поточному каталозі:
ВИХІД
quotes.txt
Переміщення файлів до нового каталогу
Після виконання наступних команд Джеймі зрозуміла, що помістила файли
sucrose.dat та maltose.dat не до того
каталогу. Файли потрібно було помістити у каталог raw.
BASH
$ ls -F
analyzed/ raw/
$ ls -F analyzed
fructose.dat glucose.dat maltose.dat sucrose.dat
$ cd analyzed
Заповніть пропуски, щоб перемістити ці файли до каталогу
raw/ (тобто туди, куди вона забула їх помістити)
Копіювання файлів і каталогів
Команда cp працює майже так само, як і mv,
але замість переміщення копіює файл. Ми можемо перевірити результат за
допомогою ls з двома шляхами у ролі параметрів, адже
ls та більшість команд Unix здатні приймати декілька
аргументів одночасно:
ВИХІД
quotes.txt thesis/quotations.txt
Ми також можемо скопіювати каталог і весь його вміст за допомогою рекурсивної опції
-r, наприклад, для створення резервної копії каталогу:
Ми можемо перевірити результат, переглянувши вміст каталогів
thesis та thesis_backup:
ВИХІД
thesis:
quotations.txt
thesis_backup:
quotations.txt
Важливо додати опцію -r. Якщо ви хочете скопіювати
каталог і не вкажете цей параметр ви побачите повідомлення про те, що
каталог було пропущено, оскільки -r не вказано.
Перейменування файлів
Припустімо, що ви створили у поточному каталозі простий текстовий
файл, який містить список статистичних тестів, які вам знадобляться для
аналізу ваших даних, і назвали його statstics.txt
Після створення і збереження цього файлу ви зрозуміли, що неправильно написали назву файлу! Ви хочете виправити помилку. Яку з наведених нижче команд ви можете використати для цього?
cp statstics.txt statistics.txtmv statstics.txt statistics.txtmv statstics.txt .cp statstics.txt .
- Ні. Хоча це створить файл з правильною назвою, неправильно названий файл все одно існуватиме у каталозі, і його потрібно буде видалити.
- Так, це спрацює для перейменування файлу.
- Ні, крапка (.) вказує, куди перемістити файл, але не надає нового імені файлу; файли з однаковими іменами не можуть бути створені.
- Ні, крапка (.) вказує, куди скопіювати файл, але не надає нового імені файлу; файли з однаковими іменами не можуть бути створені.
Переміщення та копіювання
Що виводить остання команда ls у наведеній нижче
послідовності?
ВИХІД
/Users/jamie/data
ВИХІД
proteins.dat
BASH
$ mkdir recombined
$ mv proteins.dat recombined/
$ cp recombined/proteins.dat ../proteins-saved.dat
$ ls
proteins-saved.dat recombinedrecombinedproteins.dat recombinedproteins-saved.dat
Ми розпочинаємо роботу в каталозі /Users/jamie/data і
створюємо нову папку з назвою recombined. Другий рядок
переміщує (mv) файл proteins.dat до нового
каталогу (recombined). Третій рядок робить копію файлу,
який ми щойно перемістили. Складність полягає у тому, куди саме було
скопійовано цей файл. Нагадаємо, що .. означає “піднятися
на рівень вище”, тому скопійований файл тепер знаходиться у
/Users/jamie. Зверніть увагу, що ..
інтерпретується відносно поточного робочого каталогу, а
не відносно розташування файлу, який копіюється. Отже,
єдине, що буде показано за допомогою команди ls (у каталозі
/Users/jamie/data) - це каталог
recombined.
- Ні, див. пояснення вище. Каталог
proteins-saved.datрозташовано у каталозі/Users/jamie - Так
- Ні, див. пояснення вище. Файл
proteins.datзнаходиться в каталозі/Users/jamie/data/recombined - Ні, див. пояснення вище. Файл
proteins-saved.datзнаходиться в каталозі/Users/jamie
Видалення файлів і каталогів
Повертаючись до каталогу
shell-lesson-data/exercise-data/writing, давайте почистимо
цей каталог, видаливши створений нами файл quotes.txt. Для
цього ми скористаємося командою Unix rm (скорочення від
англ. remove - видаляти):
Ми можемо перевірити видалення файлу за допомогою
ls:
ПОМИЛКА
ls: cannot access 'quotes.txt': No such file or directory
Видалення - це назавжди
В терміналі Unix немає кошика для відновлення видалених файлів (хоча у більшості графічних інтерфейсів Unix він є). Натомість коли ми видаляємо файли, вони від’єднуються від файлової системи, щоб їх місце на диску можна було використати повторно. Інструменти для пошуку та відновлення видалених файлів існують, але вони не гарантують успішного відновлення, оскільки комп’ютер може відразу перезаписати місце, яке займав файл.
Безпечне використання rm
Що відбувається, коли ми виконуємо
rm -i thesis_backup/quotations.txt? Навіщо нам може бути
потрібен цей захист при використанні rm?
ВИХІД
rm: remove regular file 'thesis_backup/quotations.txt'? y
Параметр -i призведе до окремого запиту перед (кожним)
вилученням (використовуйте Y для підтвердження вилучення або
N, щоб зберегти файл). У командному терміналі Unix немає
кошика, тому видалені файли зникнуть назавжди. Використання опції
-i дає можливість перевірити, що ми видаляємо лише обрані
файли.
Якщо ми спробуємо видалити каталог thesis за допомогою
rm thesis, ми отримаємо повідомлення про помилку:
ПОМИЛКА
rm: cannot remove `thesis': Is a directory
Це відбувається тому, що команда rm за замовчуванням
працює лише з файлами, а не з каталогами.
Команда rm може видалити каталог і весь його вміст, якщо
додати рекурсивний параметр -r, і це станеться без жодних
запитів на підтвердження:
Оскільки файли, видалені за допомогою терміналу не відновлюються,
команду rm -r слід застосовувати з великою обережністю (ви
можете додати інтерактивну опцію rm -r -i).
Операції з декількома файлами та каталогами
Час від часу нам знадобиться скопіювати або перемістити кілька файлів одночасно. Для цього треба надати список імен окремих файлів, або вказати шаблон імен за допомогою символів підстановки. Це символи, які можна використовувати для представлення невідомих символів або груп символів під час навігації по файловій системі Unix.
Копіювання кількох файлів водночас
Для цієї вправи ви можете випробувати команди у каталозі
shell-lesson-data/exercise-data.
Що робить команда cp у наведеному нижче прикладі, коли
їй надано декілька імен файлів і назву каталогу?
Що робить команда cp у наведеному нижче прикладі, коли
їй задано три або більше імен файлів?
ВИХІД
basilisk.dat minotaur.dat unicorn.dat
Якщо надано декілька імен файлів та ім’я каталогу (каталог
призначення має бути останнім аргументом), команда cp
копіює файли до вказаного каталогу.
Якщо надано тільки три імені файлів, то cp видасть
помилку, подібну до наведеної нижче, бо останній аргумент повинен бути
ім’ям каталогу.
ПОМИЛКА
cp: target 'basilisk.dat' is not a directory
Використання символів підстановки для роботи з кількома файлами одночасно
Символи підстановки
Символ * - це символ підстановки
(wildcard), який відповідає нулю або більшій кількості будь-яких
символів. Розглянемо каталог
shell-lesson-data/exercise-data/proteins:
*.pdb відповідає ethane.pdb,
propane.pdb і кожному файлу, який закінчується на ‘.pdb’. З
іншого боку, p*.pdb підходить тільки для файлів
pentane.pdb і propane.pdb, оскільки початкова
літера ‘p’ лише збігається з назвами файлів, які починаються з літери
‘p’.
Символ ? також є символом підстановки, але він
відповідає рівно одному будь-якому символу. Отже,
?ethane.pdb буде відповідати methane.pdb, тоді
як *ethane.pdb відповідає як ethane.pdb, так і
methane.pdb.
Символи підстановки можна використовувати разом, комбінуючи їх у
шаблонах. Наприклад, ???ane.pdb відповідає трьом символам,
за якими слідує ane.pdb, що дає
cubane.pdb ethane.pdb octane.pdb.
Коли термінал бачить символ підстановки, він розгортає його для
створення списку відповідних імен файлів до запуску команди,
яку було введено. Як виняток, якщо вираз підстановки не відповідає
жодному файлу, Bash передасть вираз як аргумент до команди, якою вона є.
Наприклад, введення ls *.pdf у каталозі
proteins (який містить лише файли з іменами, що
закінчуються на .pdb) призведе до повідомлення про те, що
не існує файлу з назвою *.pdf. Втім, зазвичай команди на
кшталт wc і ls показують списки імен файлів,
які відповідають цим виразам, але не самим символам підстановки. Саме
термінал, а не інші програми, виконує розкриття символів
підстановки.
Отримання переліку імен файлів, що відповідають шаблону
При виконанні в каталозі alkanes, яка з команд
ls видасть наступний результат?
ethane.pdb methane.pdb
ls *t*ane.pdbls *t?ne.*ls *t??ne.pdbls ethane.*
Відповіддю є 3.
1. показує всі файли, назви яких починаюьться з нуля або
більше символів (*), за якими йде літера t,
потім нуль або більше символів (*) і далі
ane.pdb. Це дасть
ethane.pdb methane.pdb octane.pdb pentane.pdb.
2. показує всі файли, назви яких починаються з нуля або
більше символів (*), за якими йде літера t,
потім один будь-який символ (?), потім ne. і
далі нуль або більше символів (*). Це дасть нам
octane.pdb і pentane.pdb, але не збігається ні
з чим, що закінчується на thane.pdb.
3. виправляє проблеми варіанта 2, вимагаючи два символи
(??) між t і ne. Це і є
рішення.
4. показує лише файли, що починаються з
ethane..
Більше про символи підстановки
Саманта має каталог, який містить дані калібрування, набори даних та їх описи:
BASH
.
├── 2015-10-23-calibration.txt
├── 2015-10-23-dataset1.txt
├── 2015-10-23-dataset2.txt
├── 2015-10-23-dataset_overview.txt
├── 2015-10-26-calibration.txt
├── 2015-10-26-dataset1.txt
├── 2015-10-26-dataset2.txt
├── 2015-10-26-dataset_overview.txt
├── 2015-11-23-calibration.txt
├── 2015-11-23-dataset1.txt
├── 2015-11-23-dataset2.txt
├── 2015-11-23-dataset_overview.txt
├── backup
│ ├── calibration
│ └── datasets
└── send_to_bob
├── all_datasets_created_on_a_23rd
└── all_november_files
Перед тим, як вирушити на чергову польову подорож, вона хоче створити резервну копію даних і надіслати деякі набори своєму колезі Бобу. Саманта використовує наступні команди щоб виконати цю роботу:
BASH
$ cp *dataset* backup/datasets
$ cp ____calibration____ backup/calibration
$ cp 2015-____-____ send_to_bob/all_november_files/
$ cp ____ send_to_bob/all_datasets_created_on_a_23rd/
Допоможіть Саманті, заповнивши пропуски.
Отримана структура каталогів повинна виглядати наступним чином:
BASH
.
├── 2015-10-23-calibration.txt
├── 2015-10-23-dataset1.txt
├── 2015-10-23-dataset2.txt
├── 2015-10-23-dataset_overview.txt
├── 2015-10-26-calibration.txt
├── 2015-10-26-dataset1.txt
├── 2015-10-26-dataset2.txt
├── 2015-10-26-dataset_overview.txt
├── 2015-11-23-calibration.txt
├── 2015-11-23-dataset1.txt
├── 2015-11-23-dataset2.txt
├── 2015-11-23-dataset_overview.txt
├── backup
│ ├── calibration
│ │ ├── 2015-10-23-calibration.txt
│ │ ├── 2015-10-26-calibration.txt
│ │ └── 2015-11-23-calibration.txt
│ └── datasets
│ ├── 2015-10-23-dataset1.txt
│ ├── 2015-10-23-dataset2.txt
│ ├── 2015-10-23-dataset_overview.txt
│ ├── 2015-10-26-dataset1.txt
│ ├── 2015-10-26-dataset2.txt
│ ├── 2015-10-26-dataset_overview.txt
│ ├── 2015-11-23-dataset1.txt
│ ├── 2015-11-23-dataset2.txt
│ └── 2015-11-23-dataset_overview.txt
└── send_to_bob
├── all_datasets_created_on_a_23rd
│ ├── 2015-10-23-dataset1.txt
│ ├── 2015-10-23-dataset2.txt
│ ├── 2015-10-23-dataset_overview.txt
│ ├── 2015-11-23-dataset1.txt
│ ├── 2015-11-23-dataset2.txt
│ └── 2015-11-23-dataset_overview.txt
└── all_november_files
├── 2015-11-23-calibration.txt
├── 2015-11-23-dataset1.txt
├── 2015-11-23-dataset2.txt
└── 2015-11-23-dataset_overview.txt
Упорядкування каталогів і файлів
Джеймі працює над проєктом і бачить, що її файли не дуже добре впорядковані:
ВИХІД
analyzed/ fructose.dat raw/ sucrose.dat
Файли fructose.dat та sucrose.dat містять
результати її аналізу. Яку (які) команду (команди), розглянуту
(розглянуті) у цьому уроці, їй потрібно виконати, щоб наведені нижче
команди вивели результати наведені нижче?
ВИХІД
analyzed/ raw/
ВИХІД
fructose.dat sucrose.dat
Відтворення структури каталогів
Ви починаєте новий експеримент і бажаєте продублювати структуру каталогів з попереднього експерименту, щоб потім додати нові дані.
Припустимо, що попередній експеримент знаходиться у каталозі з назвою
2016-05-18, який містить каталог data, який
аналогічно містить каталоги raw і processed у
яких містяться файли даних. Мета полягає у копіюванні структури
2016-05-18 до каталогу 2016-05-20 таким чином,
щоб ваша фінальна структура виглядала наступним чином:
ВИХІД
2016-05-20/
└── data
├── processed
└── raw
Який з наведених нижче наборів команд досягне цієї мети? Що зроблять інші команди?
Перші два набори команд досягають цієї мети. Перший набір використовує відносні шляхи для створення каталогу верхнього рівня перед створенням підкаталогів.
Третій набір команд призведе до помилки, оскільки поведінка
mkdir за замовчуванням не створює підкаталог в каталозі, що
не існує: спочатку мають бути створені каталоги проміжних рівнів.
Четвертий набір команд теж досягає цієї мети. Пам’ятайте, що опція
-p, після якої вказується шлях до одного або декількох
каталогів, змусить mkdir створити будь-які проміжні
підкаталоги за потреби.
Останній набір команд створить каталоги ‘raw’ і ‘processed’ на тому ж рівні, що і каталог ‘data’.
-
cp [old] [new]копіює файл. -
mkdir [path]створює новий каталог. -
mv [old] [new]переміщує (перейменовує) файл або каталог. -
rm [path]вилучає (видаляє) файл. -
*відповідає нулю або більшій кількості символів в імені файлу, тому*.txtвідповідає всім файлам, імена яких закінчуються на.txt. -
?відповідає будь-якому одному символу у назві файлу, тому?.txtвідповідаєa.txt, але неany.txt. - Використання клавіші Control можна описати різними способами,
зокрема
Ctrl-X,Control-Xта^X. - В терміналі немає кошика для сміття: як тільки щось видалено - його неможливо відновити.
- Більшість файлів мають назву на кшталт “щось.розширення”. Розширення не є обов’язковим і нічого не гарантує, але зазвичай використовується для позначення типу даних у файлі.
- Залежно від типу вашої роботи вам може знадобитися потужніший ніж Nano текстовий редактор.
Content from Канали та фільтри
Останнє оновлення 2025-09-04 | Редагувати цю сторінку
Приблизний час: 35 хвилин
Огляд
Питання
- Як я можу комбінувати команди, що вже існують, щоб робити нові речі?
- Як відобразити лише частину виведених даних?
Цілі
- Зрозуміти перевагу поєднання команд за допомогою каналів та фільтрів.
- Навчитись комбінувати послідовності команд для отримання нового результату
- Навчитись перенаправляти вивід команди до файлу.
- Зрозуміти, що зазвичай відбувається, якщо програмі або конвеєру не надається жодних вхідних даних для обробки.
Тепер, після ознайомлення з основними командами, ми можемо нарешті
розглянути найпотужнішу функцію терміналу: здатність комбінувати наявні
програми різними способами. Ми почнемо з каталогу
shell-lesson-data/exercise-data/proteins, який містить
шість файлів, що описують деякі прості органічні молекули. Розширення
.pdb вказує на те, що ці файли мають формат Protein Data
Bank - простий текстовий формат, який визначає тип і положення кожного
атома в молекулі.
ВИХІД
cubane.pdb methane.pdb pentane.pdb
ethane.pdb octane.pdb propane.pdb
Запустимо наприклад цю команду:
ВИХІД
20 156 1158 cubane.pdb
wc - команда для підрахунку слів (англ. ‘word count’):
вона рахує кількість рядків, слів і символів у файлах (повертаючи
значення в такому порядку зліва направо).
Якщо ми виконаємо команду wc *.pdb, то символ
* у *.pdb відповідає будь-якій кількості
символів (включаючи пустий рядок), тож термінал перетворить
*.pdb на перелік усіх файлів з розширенням
.pdb у поточному каталозі:
ВИХІД
20 156 1158 cubane.pdb
12 84 622 ethane.pdb
9 57 422 methane.pdb
30 246 1828 octane.pdb
21 165 1226 pentane.pdb
15 111 825 propane.pdb
107 819 6081 total
Зверніть увагу, що wc *.pdb в останньому рядку свого
виводу також показує загальну кількість усіх рядків у перелічених
файлах.
Якщо ми виконаємо wc -l замість просто wc,
то виводитиметься лише кількість рядків у файлах:
ВИХІД
20 cubane.pdb
12 ethane.pdb
9 methane.pdb
30 octane.pdb
21 pentane.pdb
15 propane.pdb
107 total
Параметри -m та -w з командою
wc дозволяють показувати тільки кількість символів або
тільки кількість слів у файлах.
Чому нічого не відбувається?
Що станеться, коли команді, яка має обробляти файл, не надати його назву? Наприклад, що буде, якщо ми наберемо:
але не будемо вводити *.pdb (або щось інше) після цієї
команди? Оскільки команда не отримала жодних назв файлів,
wc вважає, що треба обробляти введені дані з командного
рядка, тому вона просто очікує, поки ми надамо їй якісь дані
інтерактивно. Ззовні, однак, це виглядає так, ніби команда нічого не
робить.
Якщо ви припустилися такої помилки, ви можете вийти з цього стану, утримуючи клавішу control (Ctrl), та один раз натиснувши клавішу C: Ctrl+C. Потім відпустіть обидві клавіші.
Перехоплення виводу з команд
Який з цих файлів містить найменшу кількість рядків? Це легко визначити, коли файлів лише шість, але що робити, якщо їх 6000? Наш перший крок до пошуку рішення - це запуск наступної команди:
Символ ‘більше ніж’, тобто >, вказує терміналу
перенаправити вивід команди до файлу замість виведення
його на екран. Ця команда не виводить дані на екран, оскільки увесь
вивід wc записується до файлу lengths.txt.
Якщо файлу не існувало до виконання команди, його буде створено. Якщо
файл вже існує, він буде непомітно перезаписаний, що може призвести до
втрати даних. Таким чином, перенаправлення команд
вимагає обережності.
Команда ls lengths.txt підтверджує, що файл існує:
ВИХІД
lengths.txt
Тепер ми можемо вивести вміст файлу lengths.txt на екран
за допомогою команди cat lengths.txt. Назва команди
cat походить від слова ‘concatenate’, тобто об’єднувати, і
вона виводить вміст файлів один за одним. У цьому випадку є лише один
файл, тому cat просто виводить нам його вміст:
ВИХІД
20 cubane.pdb
12 ethane.pdb
9 methane.pdb
30 octane.pdb
21 pentane.pdb
15 propane.pdb
107 total
Виведення сторінки за сторінкою
У цьому уроці, для зручності та послідовності ми й надалі
використовуватимемо команду cat, але її недолік полягає в
тому, що вона завжди показує весь файл одразу. Більш корисною на
практиці є команда less (наприклад,
less lengths.txt). Вона виводить стільки вмісту файлу,
скільки вміщується в одному екрані, а потім робить паузу. Ви можете
перейти на один екран вперед, натиснувши пробіл, або на один екран
назад, натиснувши клавішу b. Щоб вийти з перегляду вмісту
файлу, натисніть q.
Фільтрування виводу
Далі ми скористаємося командою sort для сортування
вмісту файлу lengths.txt. Але спершу виконаємо вправу, щоб
трохи ознайомитися з командою sort:
Що робить sort -n?
Файл shell-lesson-data/exercise-data/numbers.txt містить
наступні рядки:
10
2
19
22
6
Якщо ми виконаємо команду sort для цього файлу, то
отримаємо наступне:
ВИХІД
10
19
2
22
6
Якщо ми виконаємо команду sort -n для того ж файлу, то
замість цього ми отримаємо наступне:
ВИХІД
2
6
10
19
22
Поясніть, чому -n має такий ефект.
Опція -n задає числове, а не алфавітно-цифрове
сортування.
Ми також використовуватимемо опцію -n, щоб задати
числове сортування замість алфавітно-цифрового. Це не змінить
файл; натомість відсортований результат буде виведено на екран:
ВИХІД
9 methane.pdb
12 ethane.pdb
15 propane.pdb
20 cubane.pdb
21 pentane.pdb
30 octane.pdb
107 total
Ми можемо записати відсортований список рядків в інший тимчасовий
файл з назвою sorted-lengths.txt, додавши
> sorted-lengths.txt після команди, так само як ми
використовували > lengths.txt, щоб записати вивід
wc у lengths.txt. Потім можна скористатися
командою head, щоб отримати перші кілька рядків у
sorted-lengths.txt:
ВИХІД
9 methane.pdb
Використання -n 1 з head вказує команді, що
нам потрібен лише перший рядок файлу; -n 20 поверне перші
20 тощо. Оскільки файл sorted-lengths.txt містить довжини
наших файлів, впорядковані від найменшої до найбільшої, виведенням
head має бути файл з найменшою кількістю рядків.
Що означає >>?
Ми вже розглядали оператор >, але ще існує схожий
оператор >>, який працює трохи інакше. Ми дізнаємося
про відмінності між цими двома операторами, надрукувавши кілька рядків.
Для виведення рядків ми можемо скористатися командою echo,
наприклад:
ВИХІД
The echo command prints text
Тепер протестуйте наведені нижче команди, щоб виявити різницю між цими двома операторами:
та:
Підказка: Спробуйте виконати кожну команду двічі поспіль, а потім переглянути вихідні файли.
У першому прикладі з > рядок ‘hello’ записується до
файлу testfile01.txt, але файл перезаписується кожного
разу, коли ми запускаємо команду.
З другого прикладу ми бачимо, що оператор >> також
записує рядок ‘hello’ у файл (у цьому випадку
testfile02.txt), але додає рядок до файлу, якщо останній
вже існує (тобто, коли ми запускаємо його вдруге).
Додавання даних у кінець файлу
Ми вже знайомі з командою head, яка виводить рядки з
початку файлу. Команда tail схожа на неї, але виводить
рядки з кінця файлу.
Розглянемо файл
shell-lesson-data/exercise-data/animal-counts/animals.csv.
Після виконання цих команд оберіть відповідь, яка відповідає вмісту
файлу animals-subset.csv:
- Перші три рядки файлу
animals.csv - Останні два рядки файлу
animals.csv - Перші три рядки та останні два рядки файлу
animals.csv - Другий і третій рядки файлу
animals.csv
Варіант 3 є правильним. Щоб варіант 1 був правильним, потрібно
виконати лише команду head. Щоб варіант 2 був правильним,
нам слід виконати лише команду tail. Щоб варіант 4 був
коректним, нам слід передати вивід команди head у команду
tail -n 2 виконавши
head -n 3 animals.csv | tail -n 2 > animals-subset.csv
Передача виводу іншій команді
У нашому прикладі для пошуку файлу з найменшою кількістю рядків, ми
використовуємо два проміжні файли lengths.txt та
sorted-lengths.txt для зберігання результатів. Такий підхід
може збивати з пантелику, оскільки навіть зрозумівши як працюють
wc, sort і head, ці проміжні
файли ускладнюють відстеження всього процесу. Щоб легше було зрозуміти,
можна одночасно виконати sort і head:
ВИХІД
9 methane.pdb
Вертикальна риска | між двома командами називається
каналом (pipe). Вона вказує терміналу, що вивід команди
ліворуч слід використати як вхідні дані для команди праворуч.
Це усуває необхідність у файлі sorted-lengths.txt.
Поєднання декількох команд
Ніщо не заважає нам з’єднувати канали послідовно. Наприклад, ми
можемо надсилати вивід wc безпосередньо до
sort, а потім результат — до head. Це усуває
необхідність у будь-яких проміжних файлах.
Ми почнемо з використання каналу для надсилання виводу
wc до sort:
ВИХІД
9 methane.pdb
12 ethane.pdb
15 propane.pdb
20 cubane.pdb
21 pentane.pdb
30 octane.pdb
107 total
Потім ми можемо передати цей вивід через інший канал до
head, отже повний конвеєр буде мати наступний вигляд:
ВИХІД
9 methane.pdb
Це подібне тому, як в математиці ми розглядаємо складні функції на
кшталт log(3x) і кажемо ‘логарифм трьох x*’. У нашому випадку,
обчислюється ‘head від sort від підрахунку кількості рядків у файлах
*.pdb’.
Перенаправлення та канали, використані в останніх кількох командах, проілюстровані нижче:
З’єднання команд у конвеєр
У нашому поточному каталозі ми хочемо знайти 3 файли, які мають найменшу кількість рядків. Яка з наведених нижче команд підійде для цього?
wc -l * > sort -n > head -n 3wc -l * | sort -n | head -n 1-3wc -l * | head -n 3 | sort -nwc -l * | sort -n | head -n 3
Варіант 4 є рішенням. Символ каналу | використовується
для під’єднання виводу однієї команди до входу іншої. Символ
> використовується для перенаправлення стандартного
виводу до файлу. Спробуйте це у каталозі
shell-lesson-data/exercise-data/proteins!
Інструменти, створені для співробітництва
Представлена вище можливість комбінування програм є причиною успіху
Unix. Замість створення величезних програми, які намагаються робити
багато різних речей, розробники Unix зосередилися на створенні численних
простих інструментів, кожен з яких добре виконує одну роботу і при цьому
чудово взаємодіє з іншими. Ця модель програмування називається ‘канали
та фільтри’. Ми вже бачили приклад каналів; а
фільтри — це програми на кшталт wc або
sort, які перетворюють потік вхідних даних у потік
вихідних. Майже всі стандартні інструменти Unix можуть працювати таким
чином. Якщо їм не вказано робити інше, такі програми читають дані зі
стандартного вводу, виконують з ними певні дії та записують результат у
стандартний вивід.
Головне полягає в тому, що будь-яка програма, яка зчитує рядки тексту зі стандартного вводу і записує їх у стандартний вивід, може бути об’єднана з будь-якою іншою програмою, яка працює так само. Ви можете і повинні писати свої програми таким чином, щоб ви та інші люди могли з’єднувати їх через канали і тим самим суттєво збільшуючи їхню потужність.
Розуміння роботи з каналами
Файл з назвою animals.csv (у каталозі
shell-lesson-data/exercise-data/animal-counts) містить
наступні дані:
2012-11-05,deer,5
2012-11-05,rabbit,22
2012-11-05,raccoon,7
2012-11-06,rabbit,19
2012-11-06,deer,2
2012-11-06,fox,4
2012-11-07,rabbit,16
2012-11-07,bear,1
Який текст проходить через кожен із каналів та фінальне
перенаправлення у конвеєрі нижче? Зауважте, що команда
sort -r сортує у зворотному порядку.
Підказка: створюйте конвеєр по одній команді за раз, щоб перевіряти своє розуміння
Команда head виділяє перші 5 рядків з файлу
animals.csv. Потім останні 3 рядки виділяються з попередніх
5 за допомогою команди tail. За допомогою команди
sort -r ці 3 рядки сортуються у зворотному порядку. І
нарешті, результат перенаправляється до файлу final.txt.
Вміст цього файлу можна перевірити, виконавши команду
cat final.txt. Файл повинен містити наступні рядки:
2012-11-06,rabbit,19
2012-11-06,deer,2
2012-11-05,raccoon,7
Конструювання каналу
Для файлу animals.csv з попередньої вправи розглянемо
наступну команду:
Команда cut використовується для видалення або
‘вирізання’ певних частин кожного рядка у файлі. Вона очікує, що рядки
буде розділено на стовпчики символом Tab. Символ, який
використовується таким чином, називається роздільником.
У наведеному вище прикладі ми використали опцію -d, щоб
вказати кому як роздільник. Ми також використали опцію -f,
щоб зазначити, що ми хочемо вилучити друге поле (стовпчик). Це призведе
до наступного результату:
ВИХІД
deer
rabbit
raccoon
rabbit
deer
fox
rabbit
bear
Команда uniq відфільтровує сусідні однакові рядки у
файлі. Як можна розширити цей конвеєр (за допомогою uniq та
інших команд), щоб з’ясувати, назви яких тварин містяться у файлі (без
повторень у їхніх назвах)?
Який з каналів використати?
Файл animals.csv містить 8 рядків даних, відформатованих
наступним чином:
ВИХІД
2012-11-05,deer,5
2012-11-05,rabbit,22
2012-11-05,raccoon,7
2012-11-06,rabbit,19
...
Команда uniq має опцію -c, яка підраховує
кількість разів, коли рядок зʼявляється у вхідних даних. Припускаючи що
ваш поточний каталог має назву
shell-lesson-data/exercise-data/animal-counts, яку команду
слід використати, щоб створити таблицю у файлі з підрахунком загальної
кількості тварин кожного типу?
sort animals.csv | uniq -csort -t, -k2,2 animals.csv | uniq -ccut -d, -f 2 animals.csv | uniq -ccut -d, -f 2 animals.csv | sort | uniq -ccut -d, -f 2 animals.csv | sort | uniq -c | wc -l
Варіант 4. Це правильна відповідь. Якщо вам важко зрозуміти, чому,
спробуйте виконати команди або фрагменти конвеєру (перед цим
переконайтеся, що ви перебуваєте у каталозі
shell-lesson-data/exercise-data/animal-counts).
Конвеєр Неллі: перевірка файлів
Неллі обробила свої зразки в аналізаторах і створила 17 файлів в
каталозі north-pacific-gyre, описаному раніше. Для швидкої
перевірки, вона переходить у каталог shell-lesson-data та
набирає:
На виході вона отримує 18 рядків, які виглядають наступним чином:
ВИХІД
300 NENE01729A.txt
300 NENE01729B.txt
300 NENE01736A.txt
300 NENE01751A.txt
300 NENE01751B.txt
300 NENE01812A.txt
... ...
Тепер вона набирає наступне:
ВИХІД
240 NENE02018B.txt
300 NENE01729A.txt
300 NENE01729B.txt
300 NENE01736A.txt
300 NENE01751A.txt
Ого - несподіванка! Один з файлів на 60 рядків коротший за інші. Коли вона повертається до цього файлу та перевіряє його, вона бачить, що зробила цей аналіз о 8:00 ранку в понеділок — хтось, можливо, користувався машиною на вихідних, і вона забула її перезавантажити. Перед тим, як повторно проаналізувати цей зразок, вона перевіряє, чи є файли, що містять забагато даних:
ВИХІД
300 NENE02040B.txt
300 NENE02040Z.txt
300 NENE02043A.txt
300 NENE02043B.txt
5040 total
Ці цифри мають сенс — але що робить ця ‘Z’ у другому рядку? Всі її зразки мають бути позначені ‘A’ або ‘B’; за попередньою домовленістю її лабораторія використовує ‘Z’ для позначення зразків з недостатньою інформацією. Щоб знайти інші подібні зразки, вона робить наступне:
ВИХІД
NENE01971Z.txt NENE02040Z.txt
Справді, коли вона перевіряє файл журналу на своєму ноутбуці, то
виявляється, що глибина не була записана для жодного з цих зразків.
Оскільки отримати цю інформацію іншим способом вже неможливо, їй
доведеться виключити ці два файли з аналізу. Вона може видалити їх за
допомогою rm, але деякі подальші аналізи даних не
вимагатимуть інформації про глибину, тому їй буде потрібно обережно
обирати файли за допомогою шаблонів
NENE*A.txt NENE*B.txt.
Видалення непотрібних файлів
Припустимо, ви хочете видалити файли з обробленими даними й зберегти
лише вихідні файли та скрипт обробки для економії місця у сховищі.
Вихідні файли закінчуються на .dat, а оброблені файли
закінчуються на .txt. Яка з наведених нижче команд видалить
усі оброблені файли даних і тільки їх?
rm ?.txtrm *.txtrm * .txtrm *.*
Це призведе до вилучення файлів
.txtз односимвольними назвамиЦе правильна відповідь
Термінал розширить шаблон
*до переліку усіх файлів у поточному каталозі, таким чином, команда спробує видалити всі знайдені файли та додатковий файл з назвою `.txt’Термінал розширює
*.*до переліку усіх файлів, назви яких містять принаймні одну крапку (.), включно з обробленими файлами (.txt), і вихідними файлами (.dat)
-
wcпідраховує рядки, слова та символи у своїх вхідних даних. -
catвиводить вміст своїх вхідних даних. -
sortсортує вхідні дані. -
headза замовчуванням (тобто без додаткових аргументів) виводить перші 10 рядків вхідних даних. -
tailза замовчуванням (тобто без додаткових аргументів) виводить останні 10 рядків вхідних даних. -
command > [file]перенаправляє вивід команди у файл (перезаписуючи будь-який наявний вміст цього файлу, якщо файл вже існує). -
command >> [file]додає вивід команди до файлу. -
[first] | [second]є конвеєром: вихід першої команди використовується як вхідні дані для другої. - Найкращий спосіб використання терміналу - це комбінування простих однозадачних програм (фільтрів) за допомогою каналів.
Content from Цикли
Останнє оновлення 2025-11-05 | Редагувати цю сторінку
Приблизний час: 50 хвилин
Огляд
Питання
- Як виконати одні й ті ж дії над різними файлами?
Цілі
- Написати цикл, який застосовує одну або декілька команд окремо до кожного файлу в наборі файлів.
- Простежити, яких значень набуває змінна циклу під час виконання циклу.
- Пояснити різницю між ім’ям змінної та її значенням.
- Пояснити, чому в іменах файлів не можна використовувати пробіли та деякі розділові знаки.
- Продемонструвати, як побачити, які команди були виконані останнім часом.
- Перезапустити нещодавно виконані команди без повторного введення.
Цикли - це конструкції програмування, які дозволяють повторити команду або набір команд для кожного елемента у списку. Таким чином, автоматизація виконання повторюваних дій суттєво підвищує ефективність. Подібно до шаблонів і автодоповнення, цикли допомагають зменшити кількість вручну набраного тексту (а отже, зменшують кількість помилок).
Припустимо, у нас є кілька сотень файлів даних, які містять
інформацію про геноми та мають імена на кшталт
basilisk.dat, minotaur.dat та
unicorn.dat. Для наступного прикладу ми використаємо
каталог exercise-data/creatures, який містить лише три
зразкові файли, але ті ж самі методи можна застосувати до значно більшої
кількості файлів одночасно.
Ці файли мають однакову структуру: перші три рядки містять назву виду, його класифікацію та дату оновлення, а у наступних рядках наведені послідовності ДНК. Погляньмо, що містять ці файли:
Для кожного виду ми хотіли б надрукувати його класифікацію, яка
наведена у другому рядку відповідного файлу. Для кожного файлу нам
потрібно виконати команду head -n 2 і передати її результат
через канал до команди tail -n 1. Скористаймося циклом, щоб
уникнути цю проблему, але спочатку розгляньмо загальну форму циклу,
використовуючи наведений нижче псевдокод:
BASH
# Слово "for" вказує на початок команди для виконання циклу "For"
for thing in list_of_things
# Слово "do" вказує на початок списку завдань для виконання
do
# Відступи всередині циклу не є обов'язковими, але сприяють розбірливості
operation_using/command $thing
# Слово "done" вказує на кінець циклу
done
У такому разі, ми можемо застосувати це до нашого прикладу наступним чином:
BASH
$ for filename in basilisk.dat minotaur.dat unicorn.dat
> do
> echo $filename
> head -n 2 $filename | tail -n 1
> done
ВИХІД
basilisk.dat
CLASSIFICATION: basiliscus vulgaris
minotaur.dat
CLASSIFICATION: bos hominus
unicorn.dat
CLASSIFICATION: equus monoceros
Слідкуйте за підказками командного рядка
Під час введення нашого циклу запрошення термінала змінювалося з
$ на > та назад. Друге запрошення
(>) відрізняється, щоб нагадати нам, що ми ще не
завершили введення повної команди. Крапка з комою ;
використовується для розділення двох команд, написаних в одному
рядку.
Коли термінал бачить ключове слово for, він розуміє, що
потрібно повторити команду (або групу команд) для кожного елемента зі
списку. Кожного разу, коли цикл виконується (цей процес називається
ітерацією), елемент списку послідовно присвоюється
змінній та виконуються команди всередині циклу, після
чого цикл переходить до наступного елементу списку. Усередині циклу ми
звертаємося до значення змінної, додаючи $ перед її іменем.
Символ $ повідомляє інтерпретатор командного рядка, що далі
йде назва змінної, тож слід підставити її значення, а не сприймати запис
як текст чи назву команди.
У цьому прикладі список складається з трьох файлів:
basilisk.dat, minotaur.dat та
unicorn.dat. Кожного разу, коли цикл повторюється, ми
спочатку використовуємо echo для друку значення, яке наразі
зберігає змінна $filename. Це не обов’язково робити, але
допомагає нам слідкувати за виконанням програми. Далі ми виконаємо
команду head для файлу, на який зараз посилається
$filename. При першому проходженні циклу
$filename має значення basilisk.dat.
Інтерпретатор виконує команду head над
basilisk.dat і передає перші два рядки команді
tail, яка виводить другий рядок цього файлу. Для другої
ітерації $filename стає minotaur.dat. Цього
разу термінал виконує команду head над
minotaur.dat і передає перші два рядки команді
tail, яка виводить другий рядок minotaur.dat.
На третій ітерації $filename стає unicorn.dat,
тому термінал виконує команду head для цього файлу, і
tail обробляє результат. Оскільки список містив лише три
елементи, оболонка закінчує цикл for.
Однакові символи, різні значення
Тут ми бачимо, що символ > використовується як
запрошення командного рядка, але > також застосовується
для перенаправлення виводу. Аналогічно, символ $ діє як
запрошення оболонки, але, як ми бачили раніше, його функція теж може
полягати в отриманні значення змінної.
Якщо термінал друкує > або $,
то він очікує від вас введення команди й цей символ є підказкою.
Якщо ви вводите > або $
самостійно, це означає, що ви даєте команду оболонці перенаправити вивід
або отримати значення змінної.
При використанні змінних також можна брати їхні імена у фігурні
дужки, щоб чітко відокремити імена змінних: $filename
еквівалентно ${filename}, але відрізняється від
${file}name. Ви можете побачити таку форму запису в інших
програмах.
Ми назвали змінну у цьому циклі filename (ім’я файлу),
щоб її призначення було зрозуміліше для читачів. Самій оболонці байдуже,
як називається змінна; якби ми написали цей цикл так:
або:
BASH
$ for temperature in basilisk.dat minotaur.dat unicorn.dat
> do
> head -n 2 $temperature | tail -n 1
> done
це спрацювало б точно так само. Але не робіть цього.
Програми корисні лише тоді, коли люди можуть їх розуміти, тому
беззмістовні (наприклад, x) або оманливі (наприклад,
temperature) назви підвищують ймовірність того, що програма
поводитиметься не так, як очікують читачі.
У наведених вище прикладах змінним (thing,
filename, x та temperature) можна
було б призначити будь-які інші імена, аби вони були зрозумілими як
автору коду, так і його читачу.
Також майте на увазі, що цикли можна використовувати не лише для імен файлів, а й для списків чисел або підмножини даних.
Напишіть свій власний цикл
Як би ви написали цикл, який друкує всі 10 чисел від 0 до 9?
Змінні в циклах
Ця вправа стосується каталогу
shell-lesson-data/exercise-data/alkanes. Команда
ls *.pdb дає такий результат:
ВИХІД
cubane.pdb ethane.pdb methane.pdb octane.pdb pentane.pdb propane.pdb
Що виведе наступний код?
А цей?
Чому ці два цикли дають різні результати?
Перший блок коду дає однаковий результат на кожній ітерації циклу.
Bash розгортає шаблон *.pdb в тілі циклу (а також перед
початком циклу), щоб знайти всі файли, що закінчуються на
.pdb, а потім виводить їх список за допомогою
ls. Розширений цикл матиме такий вигляд:
BASH
$ for datafile in cubane.pdb ethane.pdb methane.pdb octane.pdb pentane.pdb propane.pdb
> do
> ls cubane.pdb ethane.pdb methane.pdb octane.pdb pentane.pdb propane.pdb
> done
ВИХІД
cubane.pdb ethane.pdb methane.pdb octane.pdb pentane.pdb propane.pdb
cubane.pdb ethane.pdb methane.pdb octane.pdb pentane.pdb propane.pdb
cubane.pdb ethane.pdb methane.pdb octane.pdb pentane.pdb propane.pdb
cubane.pdb ethane.pdb methane.pdb octane.pdb pentane.pdb propane.pdb
cubane.pdb ethane.pdb methane.pdb octane.pdb pentane.pdb propane.pdb
cubane.pdb ethane.pdb methane.pdb octane.pdb pentane.pdb propane.pdb
Другий блок коду працює з іншим файлом під час кожної ітерації циклу.
Значення змінної datafile отримується за допомогою
$datafile, а потім виводиться командою ls.
ВИХІД
cubane.pdb
ethane.pdb
methane.pdb
octane.pdb
pentane.pdb
propane.pdb
Обмеження наборів файлів
Що буде виведено у результаті виконання наступного циклу в каталозі
shell-lesson-data/exercise-data/alkanes?
- Жодної назви файлу не буде виведено.
- Будуть перелічені всі файли.
- Будуть перелічені лише
cubane.pdb,octane.pdbтаpentane.pdb. - Буде виведено лише
cubane.pdb.
4 - правильна відповідь. Символ * відповідає нулю або
більшій кількості символів, тому будь-яке ім’я файлу, що починається з
літери ‘c’, за якою йдуть нуль або більша кількість символів, буде
відповідати шаблону c*.
Обмеження наборів файлів (continued)
Як зміниться результат, якщо замість цього скористатися ось цією командою?
- Будуть перелічені ті ж самі файли.
- Цього разу будуть перелічені всі файли.
- Цього разу не буде виведено жодного файлу.
- Будуть перелічені файли
cubane.pdbтаoctane.pdb. - Буде перелічено лише файл
octane.pdb.
4 - правильна відповідь. Символ * відповідає нулю або
більшій кількості символів, тому всі імена файлів з нулем або більшою
кількістю символів перед літерою ‘c’ або після літери ‘c’ будуть
відповідати шаблону *c*.
Як зберігати результати в файл під час виконання циклу - частина перша
В каталозі shell-lesson-data/exercise-data/alkanes, яким
буде результат роботи цього циклу?
- Буде виведено
cubane.pdb,ethane.pdb,methane.pdb,octane.pdb,pentane.pdbтаpropane.pdb, а текст з файлуpropane.pdbбуде збережено у файлі з назвоюalkanes.pdb. - Буде виведено
cubane.pdb,ethane.pdbтаmethane.pdb, а текст з усіх трьох файлів буде об’єднано і збережено у файлі з назвоюalkanes.pdb. - Буде виведено
cubane.pdb,ethane.pdb,methane.pdb,octane.pdbтаpentane.pdb, а текст з файлуpropane.pdbбуде збережено у файлі з назвоюalkanes.pdb. - Жоден із наведених варіантів.
- Текст з кожного файлу по черзі буде записуватися у файл
alkanes.pdb. Однак, файл буде перезаписуватися на кожній ітерації циклу, тому остаточний вмістalkanes.pdb' буде збігатися з текстом з файлуpropane.pdb`.
Як зберігати результати в файл під час виконання циклу - частина друга
У тому ж каталозі
shell-lesson-data/exercise-data/alkanes, що буде виведено у
наступному циклі?
- Весь текст з файлів
cubane.pdb,ethane.pdb,methane.pdb,octane.pdbтаpentane.pdbбуде об’єднано і збережено у файлі з назвоюall.pdb. - Текст з файлу
ethane.pdbбуде збережено до файлу з назвоюall.pdb. - Весь текст з файлів
cubane.pdb,ethane.pdb,methane.pdb,octane.pdb,pentane.pdbтаpropane.pdbбуде об’єднано та збережено у файл з назвоюall.pdb. - Весь текст з файлів
cubane.pdb,ethane.pdb,methane.pdb,octane.pdb,pentane.pdbтаpropane.pdbбуде виведено на екран і збережено у файлі з назвоюall.pdb.
3 - правильна відповідь. Оператор >> додає дані до
файлу, а не перезаписує його вміст перенаправленням виводу команди.
Оскільки вивід команди cat було перенаправлено, на екран
нічого не буде виведено.
Для наступного прикладу перейдемо у каталог
shell-lesson-data/exercise-data/creatures. Тут цикл трохи
складніший:
Термінал розпочинає роботу з розгортання *.dat, щоб
створити список файлів для подальшої обробки. Тіло
циклу виконує дві команди для кожного з них. Перша команда,
echo, виводить свої аргументи на стандартний вивід (тобто,
на standard output). Наприклад:
друкує:
ВИХІД
hello there
У цьому випадку, оскільки термінал підставить до
$filename імʼя файлу, echo $filename виведе
ім’я файлу. Зауважте, що ми не можемо написати це як:
тому що під час першої ітерації циклу, коли $filename
буде замінено на basilisk.dat, термінал спробує запустити
basilisk.dat як програму. Нарешті, комбінація
head і tail виділить рядки 81-100 з будь-якого
файлу, що наразі обробляється (за умови, що у відповідному файлі є
принаймні 100 рядків).
Пробіли в іменах
Пробіли використовуються для відокремлення елементів списку, які ми будемо перебирати у циклі. Якщо один з цих елементів містить пробіл, нам потрібно взяти його в лапки та зробити те ж саме зі змінною циклу. Припустимо, що наші файли даних мають імена:
red dragon.dat
purple unicorn.dat
Щоб переглянути ці файли у циклі, нам потрібно додати подвійні лапки, ось так:
BASH
$ for filename in "red dragon.dat" "purple unicorn.dat"
> do
> head -n 100 "$filename" | tail -n 20
> done
Простіше уникати використання пробілів (або інших спеціальних символів) у назвах файлів.
Вищевказані файли не існують, тому під час виконання цього коду
команда head не зможе знайти їх; однак у повідомленні про
помилку буде вказано, які саме файли вона намагалась відкрити:
ПОМИЛКА
head: cannot open ‘red dragon.dat' for reading: No such file or directory
head: cannot open ‘purple unicorn.dat' for reading: No such file or directory
Спробуйте видалити лапки навколо $filename у наведеному
вище циклі, щоб побачити ефект лапок на назвах з пробілами. Зверніть
увагу, що ми отримуємо результат команди циклу для
unicorn.dat коли ми запускаємо цей код у каталозі
creatures:
ВИХІД
head: cannot open ‘red' for reading: No such file or directory
head: cannot open ‘dragon.dat' for reading: No such file or directory
head: cannot open ‘purple' for reading: No such file or directory
CGGTACCGAA
AAGGGTCGCG
CAAGTGTTCC
...
Ми хочемо змінити кожен з файлів у
shell-lesson-data/exercise-data/creatures, але при цьому
зберегти оригінальні версії файлів. Наприклад, ми хочемо скопіювати
оригінальні файли до нових файлів з назвами
original-basilisk.dat та original-unicorn.dat.
Ми не можемо використати:
тому що це буде розширено до:
Це не створить резервну копію наших файлів, натомість ми отримаємо помилку:
ПОМИЛКА
cp: target `original-*.dat' is not a directory
Ця проблема виникає, коли команда cp отримує більше ніж
два вхідних аргументи. Коли це відбувається, вона очікує, що останнім
вхідним параметром буде каталог, куди вона зможе скопіювати всі файли,
які їй було передано. Оскільки у каталозі creatures немає
каталогу з назвою original-*.dat, ми отримаємо помилку.
Замість цього ми можемо використати цикл:
Цей цикл виконує команду cp один раз для кожного імені
файлу. Перший раз, коли змінна $filename має значення
basilisk.dat, термінал виконує:
Вдруге, буде виконана наступна команда:
В останній раз, команда буде такою:
Оскільки команда cp зазвичай не виводить жодного
результату, важко перевірити що цикл працює правильно. Однак ми
дізналися, як виводити рядки за допомогою echo. Це допоможе
нам перевірити, які команди виконувалися б у циклі без їх фактичного
виконання.
Наступна діаграма показує, що відбувається при виконанні зміненого
циклу, і демонструє, як доречне використання echo може
допомагати у програмуванні.
Конвеєр Неллі: Обробка файлів
Тепер Неллі готова обробити свої файли даних, використовуючи
goostats.sh — скрипт командної оболонки, який був написаний
її керівником. Він розраховує деякі статистичні параметри для зразка
білка, і приймає два аргументи:
- вхідний файл (що містить необроблені дані)
- вихідний файл (для збереження обчисленої статистики)
Оскільки вона все ще вчиться користуватися терміналом, вона вирішує
будувати потрібну послідовність команд поступово. Спершу потрібно
впевнитися, що було обрано правильні вхідні файли — ті, назви яких
закінчуються на ‘A’ або ‘B’, але не на ‘Z’. Переходячи до каталогу
north-pacific-gyre, Неллі вводить:
BASH
$ cd
$ cd Desktop/shell-lesson-data/north-pacific-gyre
$ for datafile in NENE*A.txt NENE*B.txt
> do
> echo $datafile
> done
ВИХІД
NENE01729A.txt
NENE01729B.txt
NENE01736A.txt
...
NENE02043A.txt
NENE02043B.txt
Далі треба вирішити як назвати файли, які створюватиме програма
аналізу goostats.sh. Додавання префікса ‘stats’ до назви
кожного вхідного файлу здається простим рішенням, тому вона модифікує
свій цикл відповідним чином:
ВИХІД
NENE01729A.txt stats-NENE01729A.txt
NENE01729B.txt stats-NENE01729B.txt
NENE01736A.txt stats-NENE01736A.txt
...
NENE02043A.txt stats-NENE02043A.txt
NENE02043B.txt stats-NENE02043B.txt
Насправді вона ще не запускала goostats.sh, але тепер
переконалася, що її скрипт зможе обрати потрібні файли та створити
правильні вихідні імена для результатів.
Постійне повторення одних і тих самих команд уже починає набридати, і Неллі боїться помилитися, тому замість цього вона натискає клавішу ↑. У результаті оболонка повторно показує весь цикл в один рядок (використовуючи крапку з комою для розділення його частин):
Використовуючи ←, Неллі переходить до команди
echo та змінює її на bash goostats.sh:
Коли вона натискає Enter, термінал виконує змінену команду. Однак, здається, нічого не відбувається — немає жодного виводу. Через деякий час Неллі розуміє, що оскільки її скрипт більше нічого не виводить на екран, вона не має жодного уявлення як швидко він виконується і чи працює взагалі. Вона перериває виконання команди, натискаючи Ctrl+C, та за допомогою клавіші↑ повторно викликає її та редагує, щоб вона виглядала так:
BASH
$ for datafile in NENE*A.txt NENE*B.txt; do echo $datafile;
bash goostats.sh $datafile stats-$datafile; done
Початок і кінець рядка
Щоб швидко переміститися на початок рядка в терміналі, натисніть Ctrl+A, а щоб перейти в його кінець — Ctrl+E.
Тепер, коли Неллі запускає свою програму, та виводить один рядок приблизно кожні п’ять секунд:
ВИХІД
NENE01729A.txt
NENE01736A.txt
NENE01751A.txt
...
Помножив 1518 файлів на 5 секунд і поділивши результат на 60, Неллі
підраховує що її скрипт буде виконуватися близько двох годин. Для
завершення перевірки вона відкриває нове вікно терміналу, переходить до
каталогу north-pacific-gyre та використовує команду
cat stats-NENE01729B.txt. для перегляду одного зі створених
файлів. Оскільки все працює як слід, Неллі задоволено йде зробити каву
та провести час із книжкою.
Хто знає історію, той може її повторити
Ще один спосіб відтворити попередні дії — це команда
history, яка показує перелік останніх кількох сотень
виконаних команд. Після цього можна ввести !123 (де ‘123’
замінено на номер відповідної команди), щоб запустити її знову.
Наприклад, якщо Неллі набере наступне:
ВИХІД
456 for datafile in NENE*A.txt NENE*B.txt; do echo $datafile stats-$datafile; done
457 for datafile in NENE*A.txt NENE*B.txt; do echo $datafile stats-$datafile; done
458 for datafile in NENE*A.txt NENE*B.txt; do bash goostats.sh $datafile stats-$datafile; done
459 for datafile in NENE*A.txt NENE*B.txt; do echo $datafile; bash goostats.sh $datafile
stats-$datafile; done
460 history | tail -n 5
то вона може перезапустити goostats.sh просто набравши
!459.
Інші корисні команди для роботи з історією
Окрім history, існує низка скорочень, які дозволяють
швидше переглядати та викликати попередні команди.
- Ctrl+R переходить у режим ‘зворотного пошуку’, який дозволяє знайти останню команду завдяки частині тексту. Натисніть Ctrl+R ще один або кілька разів для перегляду більш ранніх збігів. Після цього можна за допомогою стрілок вліво та вправо переміститися по знайденому рядку, відредагувати його та натиснути Return, щоб виконати команду.
-
!!повертає безпосередньо попередню команду (деякі з вас можуть знайти це більш зручним, ніж використання ↑) -
!$повертає останнє слово останньої команди. Ця можливість корисна частіше, ніж здається: післяbash goostats.sh NENE01729B.txt stats-NENE01729B.txtможна просто набратиless !$для перегляду файлуstats-NENE01729B.txt, що швидше, ніж шукати попередню команду зі ↑ та змінювати її вручну.
Пробний запуск
Цикл — це спосіб виконати багато дій одночасно — або зробити багато
помилок одразу, якщо він робить щось не те. Один зі способів перевірити
роботу циклу - замінити фактичне виконання команд на
echo.
Припустимо, ми хочемо переглянути команди, які виконає наступний цикл, без виконання цих команд:
У чому різниця між двома наведеними нижче циклами, і який із них слід запустити?
Нам потрібен саме другий варіант циклу. Він виводить на екран увесь
текст у лапках, підставивши назву змінної циклу, оскільки перед нею
стоїть знак долара. Крім того, ця команда не створює і не змінює файл
all.pdb, оскільки оператор >>
розглядається як частина рядка, а не як інструкція перенаправлення
виводу.
Перша версія додає вивід команди echo cat $datafile до
файлу all.pdb. Цей файл міститиме лише список команд типу
cat cubane.pdb, cat ethane.pdb,
cat methane.pdb тощо.
Спробуйте обидві версії самостійно, щоб побачити результат!
Обов’язково відкрийте файл all.pdb, щоб переглянути його
вміст.
Вкладені цикли
Припустімо, що ми хочемо створити систему каталогів для впорядкування певних експериментів, у яких досліджується швидкість реакцій із різними хімічними сполуками та температурами. Яким буде результат виконання наступного коду:
Ми маємо вкладений цикл, тобто такий, що міститься в іншому циклі,
тому для кожного значення змінної species у зовнішньому
циклі внутрішній цикл (вкладений цикл) перебирає список температур і
створює новий каталог для кожної комбінації.
Спробуйте запустити цей код самостійно, щоб побачити, які каталоги буде створено!
- Цикл
forповторює команди один раз для кожного елемента списку. - У кожному циклі
forвикористовується змінна, що вказує на поточний об’єкт, з яким він зараз працює. - Використовуйте
$nameдля підстановки змінної (тобто отримання її значення). Також можна використовувати${name}. - Не варто використовувати пробіли, лапки чи символи підстановки, такі як ‘*’ або ‘?’, у назвах файлів, адже це може призвести до помилок під час роботи зі змінними.
- Надавайте файлам послідовні імена, які можна легко описати за допомогою шаблонів, щоб полегшити їх вибір для циклів.
- Щоб швидко знайти й повторити попередню команду, скористайтеся клавішею зі стрілкою вгору — це дозволяє редагувати та виконувати її без повторного введення.
- Використовуйте Ctrl+R для пошуку попередньо введених команд.
- Використовуйте команду
history, щоб побачити перелік останніх команд; також застосовуйте![номер]для повторення команди за її номером.
Content from Скрипти командної оболонки
Останнє оновлення 2025-11-26 | Редагувати цю сторінку
Приблизний час: 45 хвилин
Огляд
Питання
- Як я можу зберігати та повторно використовувати команди?
Цілі
- Написати скрипт командної оболонки, який виконує одну або декілька команд для заздалегідь визначеного набору файлів.
- Запустити скрипт командної оболонки з термінала.
- Написати скрипт командної оболонки, який обробляє файли, вказані користувачем у командному рядку.
- Створити конвеєри, що використовують скрипти оболонки, створені вами та іншими користувачами.
Нарешті ми готові дізнатися, чому оболонка є таким потужним середовищем програмування. Ми збираємося зібрати та зберегти у файлах часто використовувані команди, щоб пізніше можна було виконати всі ці дії одночасно, набравши лише одну команду. З історичних причин скопійовані в файл команди зазвичай називають командним скриптом, скриптом командної оболонки, або скриптом терміналу, але не помиляйтеся: це насправді невеликі програми.
Написання командних скриптів не тільки прискорить вашу роботу, а й дозволить уникнути постійного повторного введення тих самих команд. Крім того, це підвищить якість вашої роботи (зменшить ризик друкарських помилок) і полегшить її відтворення. Якщо ви повернетеся до своєї роботи пізніше (або якщо хтось знайде вашу роботу і захоче її використати), відтворити ті ж результати можна буде просто запустивши скрипт, без потреби пригадувати та повторно вводити довгий перелік команд.
Спершу повернемося до каталогу alkanes/ і створимо новий
файл middle.sh, який стане нашим скриптом терміналу:
Команда nano middle.sh відкриває файл
middle.sh у текстовому редакторі ‘nano’ (який запускається
у терміналі). Якщо файл не існує, його буде створено. Ми можемо
скористатися текстовим редактором для безпосереднього редагування файлу,
додавши до нього наступний рядок:
head -n 15 octane.pdb | tail -n 5
Це варіант каналу, який ми побудували раніше: він вибирає рядки 11-15
файлу octane.pdb. Пам’ятайте, ми поки не
запускаємо його як команду: ми лише записуємо команди у файл.
Потім ми зберігаємо файл (Ctrl-O у nano) і виходимо з
текстового редактора (Ctrl-X у nano). Переконайтеся, що в
каталозі alkanes тепер міститься файл з назвою
middle.sh.
Після того, як ми зберегли файл, ми можемо дати оболонці команду
виконати його вміст. Оскільки термінал називається bash, ми
виконаємо наступну команду:
ВИХІД
ATOM 9 H 1 -4.502 0.681 0.785 1.00 0.00
ATOM 10 H 1 -5.254 -0.243 -0.537 1.00 0.00
ATOM 11 H 1 -4.357 1.252 -0.895 1.00 0.00
ATOM 12 H 1 -3.009 -0.741 -1.467 1.00 0.00
ATOM 13 H 1 -3.172 -1.337 0.206 1.00 0.00
Дійсно, результат роботи скрипту збігається з тим, що ми отримали б, запустивши конвеєр напряму у терміналі.
Текст або будь-що інше?
Зазвичай ми називаємо “текстовими редакторами” програми на кшталт
Microsoft Word або LibreOffice Writer, але коли мова йде про
програмування, потрібно бути трохи обережнішими. За замовчуванням,
Microsoft Word зберігає у файлах .docx не лише текст, але й
інформацію про форматування: шрифти, заголовки тощо. Ця додаткова
інформація не зберігається у вигляді звичайних символів і є незрозумілою
для програм на кшталт head, яка очікує на те, що у файлі
будуть тільки літери, числа та пунктуація зі стандартної комп’ютерної
клавіатури. Отже, редагуючи програми, вам слід користуватися текстовим
редактором, який працює зі звичайним текстом, або подбати про те, щоб
файли зберігалися у форматі звичайного тексту.
Що робити, якщо потрібно вибрати рядки з будь-якого файлу? Ми могли б
щоразу редагувати middle.sh для зміни імені файлу, але це,
ймовірно, зайняло б більше часу, ніж повторне введення й виконання
команди у терміналі з новим ім’ям. Натомість відредагуймо
middle.sh і зробимо його більш універсальним:
Тепер у “nano” замініть текст octane.pdb на спеціальну
змінну з назвою $1:
head -n 15 "$1" | tail -n 5
У командному скрипті змінна $1 позначає перший аргумент
командного рядка – перше ім’я файлу (або інший аргумент). Тепер ми
можемо запустити наш скрипт наступним чином для того ж самого файлу:
ВИХІД
ATOM 9 H 1 -4.502 0.681 0.785 1.00 0.00
ATOM 10 H 1 -5.254 -0.243 -0.537 1.00 0.00
ATOM 11 H 1 -4.357 1.252 -0.895 1.00 0.00
ATOM 12 H 1 -3.009 -0.741 -1.467 1.00 0.00
ATOM 13 H 1 -3.172 -1.337 0.206 1.00 0.00
або ж запустити з іншим файлом ось так, вказавши його імʼя подібним чином:
ВИХІД
ATOM 9 H 1 1.324 0.350 -1.332 1.00 0.00
ATOM 10 H 1 1.271 1.378 0.122 1.00 0.00
ATOM 11 H 1 -0.074 -0.384 1.288 1.00 0.00
ATOM 12 H 1 -0.048 -1.362 -0.205 1.00 0.00
ATOM 13 H 1 -1.183 0.500 -1.412 1.00 0.00
Подвійні лапки навколо аргументів
Як і у випадку зі змінною циклу, $1 потрібно брати в
подвійні лапки, оскільки назва файлу містить пробіли.
Наразі нам доводиться редагувати middle.sh щоразу, коли
ми хочемо змінити діапазон рядків, які повертаються. Ми виправимо це,
налаштувавши наш скрипт для використання трьох аргументів командного
рядка. Після першого аргументу командного рядка ($1),
наступні надані аргументи будуть зберігатися у спеціальних змінних
$1, $2, $3, які відповідно
посилаються на перший, другий і третій аргумент командного рядка.
Знаючи це, ми можемо використовувати додаткові аргументи для
визначення діапазону рядків, які треба передати до head та
tail:
head -n "$2" "$1" | tail -n "$3"
Тепер ми можемо запустити:
ВИХІД
ATOM 9 H 1 1.324 0.350 -1.332 1.00 0.00
ATOM 10 H 1 1.271 1.378 0.122 1.00 0.00
ATOM 11 H 1 -0.074 -0.384 1.288 1.00 0.00
ATOM 12 H 1 -0.048 -1.362 -0.205 1.00 0.00
ATOM 13 H 1 -1.183 0.500 -1.412 1.00 0.00
Достатньо змінити аргументи команди й скрипт працюватиме по-іншому:
ВИХІД
ATOM 14 H 1 -1.259 1.420 0.112 1.00 0.00
ATOM 15 H 1 -2.608 -0.407 1.130 1.00 0.00
ATOM 16 H 1 -2.540 -1.303 -0.404 1.00 0.00
ATOM 17 H 1 -3.393 0.254 -0.321 1.00 0.00
TER 18 1
Такий варіант працює, але іншому користувачеві може знадобитися
певний час, щоб розібратися, як саме працює скрипт
middle.sh. Щоб зробити скрипт зрозумілішим, додамо на його
початку кілька коментарів:
# Виділення рядків з середини файлу.
# Використання: bash middle.sh filename end_line num_lines
head -n "$2" "$1" | tail -n "$3"
Коментар починається зі символу # і триває до кінця
рядка. Коментарі не впливають на виконання коду, але вони допомагають
користувачам (і вам самим у майбутньому) швидко зрозуміти та
використовувати скрипти. Єдине застереження полягає у тому, що кожного
разу, коли ви змінюєте скрипт, ви повинні перевіряти, що коментар все ще
правильний. Пояснення, яке спрямовує читача в неправильному напрямку,
гірше, ніж його відсутність.
Що робити, якщо ми хочемо обробити багато файлів в одному конвеєрі?
Наприклад, якщо ми хочемо відсортувати наші .pdb-файли за
довжиною, ми введемо:
оскільки wc -l виводить кількість рядків у файлах
(нагадаємо, що wc означає ‘підрахунок слів’ (word count), а
додавання опції -l натомість означає ‘підрахунок рядків’
(lines)) та sort -n використовує числове сортування. Ми
можемо записати цей конвеєр у файл, але тоді він сортуватиме лише список
.pdb файлів у поточному каталозі. Якщо ми хочемо отримати
відсортований список інших типів файлів, нам потрібно передати всі ці
імена у скрипт. У цьому випадку не можна скористатися змінними
$1, $2 тощо, бо ми не знаємо наперед, скільки
файлів потрібно обробити. Натомість ми використовуємо спеціальну змінну
$@, що означає, “Всі аргументи командного рядка передані
скрипту”. Необхідно взяти $@ у подвійні лапки, щоб
правильно обробляти аргументи з пробілами ("$@" є
спеціальним синтаксисом еквівалентним "$1"
"$2" …).
Ось приклад:
# Сортування файлів за їх розміром.
# Використання: bash sorted.sh one_or_more_filenames
wc -l "$@" | sort -n
ВИХІД
9 methane.pdb
12 ethane.pdb
15 propane.pdb
20 cubane.pdb
21 pentane.pdb
30 octane.pdb
163 ../creatures/basilisk.dat
163 ../creatures/minotaur.dat
163 ../creatures/unicorn.dat
596 total
Перелік унікальних видів тварин
Лія має кілька сотень файлів даних, кожен з яких відформатований наступним чином:
2013-11-05,deer,5
2013-11-05,rabbit,22
2013-11-05,raccoon,7
2013-11-06,rabbit,19
2013-11-06,deer,2
2013-11-06,fox,1
2013-11-07,rabbit,18
2013-11-07,bear,1
Приклад файлу такого типу наведено у
shell-lesson-data/exercise-data/animal-counts/animals.сsv.
Ми можемо скористатися командою
cut -d , -f 2 animals.csv | sort | uniq, щоб отримати
унікальні види тварин з файлу animals.csv. Щоб заощадити
час і не повторювати введення команд, науковець може замість цього
написати скрипт командної оболонки.
Створіть скрипт із назвою species.sh, який сприймає
довільну кількість імен файлів за аргументи командного рядка. Він має
використовувати змінену версію попередньої команди для виведення списку
унікальних видів, які зустрічаються в кожному з цих файлів окремо.
Припустимо, ми щойно виконали низку команд, які зробили щось корисне — наприклад, створили графік, який ми плануємо використати у публікації. Ми хотіли б мати змогу відтворити графік пізніше, якщо знадобиться, тому збережемо команди у файл. Замість повторного введення (і ризику помилок), ми можемо зробити ось так:
Файл redo-figure-3.sh тепер містить наступне:
297 bash goostats.sh NENE01729B.txt stats-NENE01729B.txt
298 bash goodiff.sh stats-NENE01729B.txt /data/validated/01729.txt > 01729-differences.txt
299 cut -d ',' -f 2-3 01729-differences.txt > 01729-time-series.txt
300 ygraph --format scatter --color bw --borders none 01729-time-series.txt figure-3.png
301 history | tail -n 5 > redo-figure-3.sh
Після невеликого редагування для видалення номерів команд і
останнього рядка з командою history, ми отримаємо абсолютно
точний запис того, як було створено цей графік.
Чому варто записувати команди в історію перед їх виконанням?
Якщо виконати команду:
останньою командою у файлі є сама команда history,
тобто, термінал додав history до журналу команд перед тим,
як фактично її виконав. Насправді термінал завжди додає команди
до журналу перед їх виконанням. Як ви гадаєте, чому він поводиться саме
так?
Якщо якась команда призводить до збою або зависання, знання того, яка саме команда це спричинила, допоможе з’ясувати причину проблеми. Якби команда записувалася лише після її виконання, ми б втратили запис останньої команди у разі збою.
На практиці, більшість людей створюють скрипти терміналу, запускаючи
команди в командному рядку кілька разів, щоб переконатися, що вони
роблять все правильно, а потім зберігають їх у файлі для подальшого
використання. Такий підхід дозволяє повторно відтворити робочий процес
та дослідження даних, за допомогою одного виклику history і
невеликого редагування для впорядкування команд та їх збереження як
скрипт терміналу.
Конвеєр Неллі: створення скрипту
Науковий керівник Неллі наполягав на тому, що вся її аналітика має бути відтворюваною. Найпростіший спосіб зберегти всі кроки - записати їх у скрипт.
Спочатку повернемося до каталогу проєкту Неллі:
За допомогою nano вона створює файл …
…який містить наступне:
BASH
# Розрахунок статистики для файлів даних.
for datafile in "$@"
do
echo $datafile
bash goostats.sh $datafile stats-$datafile
done
Вона зберігає цей код у файлі з назвою do-stats.sh, щоб
тепер мати змогу повторно виконати перший етап аналізу, набравши:
Вона також може зробити наступне:
щоб вивести лише кількість оброблених файлів, а не їхні назви.
Одна з важливих особливостей скрипту Неллі полягає в тому, що він дозволяє користувачеві самостійно вибирати, які файли потрібно обробляти. Вона могла б також написати його так:
BASH
# Розрахунок статистики для файлів з локацій A та B.
for datafile in NENE*A.txt NENE*B.txt
do
echo $datafile
bash goostats.sh $datafile stats-$datafile
done
Перевага цього буде полягати в тому, що цей код завжди вибирає правильні файли, і Неллі не потрібно пам’ятати про виключення файлів із літерою ‘Z’. Недолік полягає в тому, що скрипт завжди обробляє лише ці файли. Не редагуючи скрипт, Неллі не може застосувати його до всіх файлів (у тому числі до файлів ‘Z’) або до файлів ‘G’ чи ‘H’, які створюють її колеги в Антарктиді. Якщо вона хотіла б піти далі, то могла б модифікувати свій скрипт для перевірки аргументів командного рядка та за замовчуванням використовував NENE_A.txt NENE_B.txt, якщо жодних аргументів не передано. Звичайно, це створює інший компроміс між гнучкістю і складністю.
Змінні в скриптах терміналу
Уявіть, що у каталозі alkanes у вас є скрипт з назвою
script.sh, який містить наступні команди:
Перебуваючи у каталозі alkanes, ви вводите наступну
команду:
Які з наведених нижче результатів ви очікуєте побачити?
- Усі рядки між першим та останнім рядками кожного файлу, що
закінчується на
.pdbу каталозіalkanes - Перший та останній рядок кожного файлу, що закінчується на
.pdbу каталозіalkanes - Перший та останній рядок кожного файлу в каталозі
alkanes - Помилку через лапки навколо
*.pdb
Правильною є відповідь 2.
Спеціальні змінні $1, $2 та $3 відповідають аргументам командного рядка, що передаються скрипту, тому виконуються наступні команди:
BASH
$ head -n 1 cubane.pdb ethane.pdb octane.pdb pentane.pdb propane.pdb
$ tail -n 1 cubane.pdb ethane.pdb octane.pdb pentane.pdb propane.pdb
Термінал не розгортає '*.pdb', оскільки символи взято у
лапки. Таким чином, першим аргументом скрипту є '*.pdb',
який буде розгорнуто у скрипті за допомогою head і
tail.
Пошук найдовшого файлу із заданим розширенням
Напишіть сценарій терміналу з назвою longest.sh, який
отримує в якості аргументів ім’я каталогу і розширення імені файлу як
аргументи, і виводить назву файлу з найбільшою кількістю рядків у цьому
каталозі з цим розширенням. Наприклад:
виведе назву файлу .pdb у каталозі
shell-lesson-data/exercise-data/proteins, який має
найбільшу кількість рядків.
Ви можете протестувати свій скрипт в іншому каталозі, наприклад
BASH
# Скрипт терміналу, який приймає два аргументи:
# 1. ім'я каталогу
# 2. розширення файлу
# і виводить ім'я файлу з даним розширенням в цьому каталозі
# який має найбільшу кількість рядків
wc -l $1/*.$2 | sort -n | tail -n 2 | head -n 1
Перша частина конвеєра, wc -l $1/*.$2 | sort -n, рахує
кількість рядків у кожному файлі та сортує їх у числовому порядку
(найбільший файл буде останнім). Коли надано кілька файлів,
wc також виведе останній підсумковий рядок, який покаже
загальну кількість рядків у всіх файлах. Ми використовуємо
tail -n 2 | head -n 1, щоб відкинути цей останній
рядок.
Використовуючи wc -l $1/*.$2 | sort -n | tail -n 1, ми
побачимо останній підсумковий рядок. Ми також можемо будувати конвеєр
крок за кроком, щоб краще зрозуміти результат.
Читання і розуміння скриптів
Для цього завдання ще раз розглянемо каталог
shell-lesson-data/exercise-data/proteins. У ньому міститься
низка файлів .pdb разом з іншими файлами, які ви могли
створити. Опишіть, що відбудеться при послідовному виконанні кожного з
трьох скриптів із командами bash script1.sh *.pdb,
bash script2.sh *.pdb та
bash script3.sh *.pdb.
У кожному випадку термінал розгортає символ підстановки у
*.pdb, а потім передає отриманий список файлів як аргументи
скрипту.
Скрипт 1 виведе список усіх файлів, що містять крапку в їх назві. Передані скрипту аргументи взагалі не використовуються.
Скрипт 2 виведе вміст перших 3 файлів з розширенням
.pdb. $1, $2 і $3
відповідають першому, другому та третьому аргументам відповідно.
Скрипт 3 виведе всі аргументи скрипту (тобто назви всіх файлів з
розширенням .pdb), і додасть до них .pdb.
Змінна $@ зазначає усі аргументи, що були передані
скрипту.
ВИХІД
cubane.pdb ethane.pdb methane.pdb octane.pdb pentane.pdb propane.pdb.pdb
Налагодження скриптів
Припустимо, ви зберегли наступний скрипт у файлі з назвою
do-errors.sh у каталозі
north-pacific-gyre/scripts:
BASH
# Статистичні розрахунки для файлів даних.
for datafile in "$@"
do
echo $datfile
bash goostats.sh $datafile stats-$datafile
done
Якщо ви запускаєте його з каталогу
north-pacific-gyre:
програма нічого не виводить. Щоб з’ясувати причину, перезапустіть
скрипт з опцією -x:
Що показує вивід? Який рядок призводить до помилки?
Параметр -x призводить до запуску скрипту у режимі
налагодження (відлагодження). Він виводить кожну команду під час її
виконання, допомагаючи вам локалізувати помилки. У цьому прикладі ми
таким чином можемо побачити, що команда echo нічого не
виводить. Ми допустили друкарську помилку у назві змінної циклу, і
оскільки змінної datfile не існує, вона повертає порожній
рядок.
- Зберігайте команди у файлах (які зазвичай називають скриптами оболонки або скриптами терміналу) для їх повторного використання.
-
bash [ім'я файлу]виконує команди, збережені у відповідному файлі. -
$@посилається на всі аргументи командного рядка, передані скрипту оболонки. -
$1,$2і так далі представляють перший, другий та наступні аргументи командного рядка. - Беріть змінні в лапки, якщо їхні значення можуть містити пробіли.
- Надання користувачам можливості самим обирати файли для обробки робить скрипт гнучкішим і більш узгодженим із вбудованими командами Unix.
Content from Пошук з командного рядка
Останнє оновлення 2025-11-27 | Редагувати цю сторінку
Приблизний час: 45 хвилин
Огляд
Питання
- Як я можу знайти потрібні файли?
- Як знайти щось у файлах?
Цілі
- Використати
grepдля пошуку у текстових файлах рядків, які відповідають простим шаблонам. - Використати
findдля пошуку файлів і каталогів, назви яких відповідають простим шаблонам. - Використати вихідні дані однієї команди як аргумент(и) командного рядка для іншої команди.
- Пояснити, що мається на увазі під ‘текстовими’ та ‘бінарними’ файлами, і чому багато поширених інструментів погано працюють з останніми.
Так само, як багато хто з нас зараз використовує ‘Google’ як дієслово, що означає ‘шукати’, Unix-програмісти часто використовують слово ‘grep’. ‘grep’ - це скорочення від ‘global/regular expression/print’ (з англ. ‘глобальний/регулярний вираз/друк’), поширена послідовність операцій у ранніх текстових редакторах Unix. Це також назва дуже корисної програми командного рядка.
grep шукає і виводить рядки у файлах, які відповідають
шаблону. У нашому прикладі ми використаємо файл, який містить три хайку,
взяті з конкурсу
1998 року в журналі Salon (авторство належить Біллу Торкасо
(Bill Torcaso), Говарду Кордеру (Howard Korder) та Маргарет Сігал
(Margaret Segall), відповідно. Див. Haiku Error Messages в архіві
[Сторінка 1] (https://web.archive.org/web/20000310061355/http://www.salon.com/21st/chal/1998/02/10chal2.html)
та Сторінка
2 .). Для цього набору прикладів ми будемо працювати у підкаталозі
writing:
ВИХІД
The Tao that is seen
Is not the true Tao, until
You bring fresh toner.
With searching comes loss
and the presence of absence:
"My Thesis" not found.
Yesterday it worked
Today it is not working
Software is like that.
Знайдемо рядки, які містять слово ‘not’:
ВИХІД
Is not the true Tao, until
"My Thesis" not found
Today it is not working
У цьому випадку not — це шаблон для пошуку. Команда
grep шукає у файлі збіги із заданим шаблоном. Щоб
скористатися нею, введіть grep, далі шаблон для пошуку, а
потім назву файлу (або файлів), у якому (у яких) ми шукаємо.
У вихідний файл виводяться три рядки, які містять літери ‘not’.
За замовчуванням grep шукає шаблон з урахуванням
регістру. Також обраний нами шаблон пошуку не обов’язково повинен бути
повним словом, як показано в наступному прикладі.
Відшукаймо тепер шаблон ‘The’.
ВИХІД
The Tao that is seen
"My Thesis" not found.
Цього разу буде виведено два рядки з літерами ‘The’, і один із них містить наш шаблон пошуку всередині довшого слова ‘Thesis’.
Щоб обмежити збіги до рядків, що містять слово ‘The’ окремо, а не як
частинку іншого слова, ми використаємо grep з опцією
-w. Це обмежить збіги лише межами повних слів.
Пізніше у цьому уроці ми також побачимо, як можна змінити поведінку
пошуку grep стосовно чутливості до регістру.
ВИХІД
The Tao that is seen
Зауважте, що ‘межа слова’ включає початок і кінець рядка, а не лише
літери, оточені пробілами. Іноді ми хочемо шукати не окреме слово, а
фразу. Це також легко зробити за допомогою grep, взявши
фразу в лапки.
ВИХІД
Today it is not working
Ми вже бачили, що не обов’язково брати в лапки окремі слова, але лапки варто використовувати під час пошуку кількох слів. Це також допомагає легше відрізнити пошуковий термін або фразу від файлу, в якому відбувається пошук. У наступних прикладах ми будемо використовувати лапки.
Ще одна корисна опція - це -n, яка додає до виводу
номери знайдених рядків:
ВИХІД
5:With searching comes loss
9:Yesterday it worked
10:Today it is not working
Ми бачимо, що рядки 5, 9 і 10 містять літери ‘it’.
Ми можемо комбінувати опції (тобто прапорці) так само як і в інших
командах Unix. Наприклад, знайдемо рядки, які містять слово ‘the’. Ми
можемо комбінувати опцію -w для пошуку рядків зі словом
‘the’, та опцію -n для нумерації рядків із
результатами:
ВИХІД
2:Is not the true Tao, until
6:and the presence of absence:
Тепер ми хочемо використати опцію -i, щоб зробити наш
пошук нечутливим до регістру:
ВИХІД
1:The Tao that is seen
2:Is not the true Tao, until
6:and the presence of absence:
Тепер використаймо опцію -v для зворотного пошуку, тобто
виводу рядків, які не містять слова ‘the’.
ВИХІД
1:The Tao that is seen
3:You bring fresh toner.
4:
5:With searching comes loss
7:"My Thesis" not found.
8:
9:Yesterday it worked
10:Today it is not working
11:Software is like that.
Якщо ми використовуємо опцію -r (recursive, з англ. -
рекурсивний), grep може шукати шаблон рекурсивно у
підкаталогах.
Виконаймо рекурсивний пошук слова Yesterday у каталозі
shell-lesson-data/exercise-data/writing:
ВИХІД
./LittleWomen.txt:"Yesterday, when Aunt was asleep and I was trying to be as still as a
./LittleWomen.txt:Yesterday at dinner, when an Austrian officer stared at us and then
./LittleWomen.txt:Yesterday was a quiet day spent in teaching, sewing, and writing in my
./haiku.txt:Yesterday it worked
grep має багато інших опцій. Щоб переглянути їх, ми
можемо ввести:
ВИХІД
Usage: grep [OPTION]... PATTERN [FILE]...
Search for PATTERN in each FILE or standard input.
PATTERN is, by default, a basic regular expression (BRE).
Example: grep -i 'hello world' menu.h main.c
Regexp selection and interpretation:
-E, --extended-regexp PATTERN is an extended regular expression (ERE)
-F, --fixed-strings PATTERN is a set of newline-separated fixed strings
-G, --basic-regexp PATTERN is a basic regular expression (BRE)
-P, --perl-regexp PATTERN is a Perl regular expression
-e, --regexp=PATTERN use PATTERN for matching
-f, --file=FILE obtain PATTERN from FILE
-i, --ignore-case ignore case distinctions
-w, --word-regexp force PATTERN to match only whole words
-x, --line-regexp force PATTERN to match only whole lines
-z, --null-data a data line ends in 0 byte, not newline
Miscellaneous:
... ... ...
Використання grep
Яка команда призведе до наступного результату:
ВИХІД
and the presence of absence:
grep "of" haiku.txtgrep -E "of" haiku.txtgrep -w "of" haiku.txtgrep -i "of" haiku.txt
Правильна відповідь 3, тому що опція -w шукає збіги лише
між цілими словами. Інші варіанти також шукатимуть збіги зі словом ‘of’,
якщо воно є частиною іншого слова.
Символи підстановки
Проте справжня сила grep полягає не у його опціях, а у
тому, що шаблони можуть містити символи підстановки. (Технічний термін
для них - регулярні вирази (regular expressions) - саме
це має на увазі ‘re’ у слові ‘grep’). Регулярні вирази є водночас
складними й потужними; якщо ви хочете виконувати розширені пошуки,
перегляньте цей
урок на нашому сайті. Як короткий приклад, ми можемо знайти рядки, у
яких літера ‘o’ знаходиться на другій позиції, ось так:
ВИХІД
You bring fresh toner.
Today it is not working
Software is like that.
Ми використовуємо опцію -E і беремо шаблон у лапки, щоб
оболонка не намагалася його інтерпретувати іншим чином. (Наприклад, якщо
шаблон містить *, то оболонка спробує розгорнути його перед
виконанням grep.) Символ ^ у шаблоні вимагає,
щоб збіг був на початку рядка. Символ . відповідає одному
символу (подібно до ? у командному рядку), тоді як
o відповідає справжній літері ‘o’.
Відстеження видів диких тварин
Лея має кілька сотень файлів даних, збережених в одному каталозі, кожен з яких відформатовано таким чином:
2012-11-05,deer,5
2012-11-05,rabbit,22
2012-11-05,raccoon,7
2012-11-06,rabbit,19
2012-11-06,deer,2
2012-11-06,fox,4
2012-11-07,rabbit,16
2012-11-07,bear,1
Вона хоче створити командний скрипт, який використовує вид тварини як
перший аргумент командного рядка, а каталог — як другий. Скрипт повинен
повернути один файл з назвою <species>.txt, який
містить список дат і кількість особин цього виду, які були помічені для
кожної дати. Наприклад, використовуючи дані, показані вище,
rabbit.txt буде містити:
2012-11-05,22
2012-11-06,19
2012-11-07,16
Нижче кожен рядок містить окрему команду або канал. Розташуйте їх у правильному порядку в одній команді, щоб допомогти Леї досягти її мети:
Підказка: перегляньте man grep для інформації про
рекурсивний пошук у каталогах і man cut для виділення
декількох полів у рядку.
Приклад файлу такого типу наведено у
shell-lesson-data/exercise-data/animal-counts/animals.сsv.
grep -w $1 -r $2 | cut -d : -f 2 | cut -d , -f 1,3 > $1.txt
Насправді ви можете поміняти місцями порядок двох команд
cut, і це все одно буде працювати. У командному рядку
спробуйте це з командами cut і перегляньте вивід після
кожного етапу, щоб зрозуміти, чому це відбувається.
Ось як слід запускати наведений вище скрипт:
“Маленькі жінки”
Ви з другом щойно закінчили читати “Маленькі жінки” Луїзи Мей Елкотт
і дискутуєте. З чотирьох сестер у книзі — Джо, Мег, Бет і Емі — ваш друг
вважає, що Джо згадувалася найчастіше. Ви, однак, впевнені, що це Емі.
На щастя, у вас є файл LittleWomen.txt, який містить повний
текст роману
(shell-lesson-data/exercise-data/writing/LittleWomen.txt).
Використовуючи цикл for, як можна вивести звіт про те,
скільки разів згадується кожна з чотирьох сестер?
Підказка: один варіант відповіді може використовувати команди
grep, wc та | разом, а інший може
використовувати опції команди grep. Зазвичай існує кілька
способів розв’язання задачі програмування, вибір рішення залежить від
комбінації отримання правильного результату, елегантності, читабельності
та швидкості.
for sis in Jo Meg Beth Amy
do
echo $sis:
grep -ow $sis LittleWomen.txt | wc -l
done
Альтернативне, трохи гірше рішення:
for sis in Jo Meg Beth Amy
do
echo $sis:
grep -ocw $sis LittleWomen.txt
done
Це рішення є гіршим, оскільки grep -c повідомляє лише
про кількість знайдених рядків. Загальна кількість збігів, отриманих за
допомогою цього методу, буде меншою, якщо в одному рядку є більше ніж
один збіг.
Уважні спостерігачі могли помітити, що імена персонажів іноді
пишуться великими літерами у назвах розділів (наприклад, “MEG GOES TO
VANITY FAIR”). Якщо ви хочете врахувати й ці випадки, можна додати опцію
-i для нечутливості до регістру (хоча в цьому випадку це не
впливає на відповідь, яка сестра згадується найчастіше).
Поки grep знаходить рядки у файлах, команда
find знаходить самі файли. Знову ж таки, у неї є багато
опцій; щоб продемонструвати, як працюють найпростіші з них, ми
скористаємося структурою каталогів
shell-lesson-data/exercise-data, наведеною нижче.
ВИХІД
.
├── animal-counts/
│ └── animals.csv
├── creatures/
│ ├── basilisk.dat
│ ├── minotaur.dat
│ └── unicorn.dat
├── numbers.txt
├── alkanes/
│ ├── cubane.pdb
│ ├── ethane.pdb
│ ├── methane.pdb
│ ├── octane.pdb
│ ├── pentane.pdb
│ └── propane.pdb
└── writing/
├── haiku.txt
└── LittleWomen.txt
Каталог exercise-data містить один файл
numbers.txt та чотири підкаталоги:
animal-counts, creatures,
proteins і writing, кожен з яких містить різні
файли.
Для початку виконаймо find . (не забудьте запустити цю
команду з каталогу shell-lesson-data/exercise-data).
ВИХІД
.
./writing
./writing/LittleWomen.txt
./writing/haiku.txt
./creatures
./creatures/basilisk.dat
./creatures/unicorn.dat
./creatures/minotaur.dat
./animal-counts
./animal-counts/animals.csv
./numbers.txt
./alkanes
./alkanes/ethane.pdb
./alkanes/propane.pdb
./alkanes/octane.pdb
./alkanes/pentane.pdb
./alkanes/methane.pdb
./alkanes/cubane.pdb
Як завжди, символ . сам по собі позначає поточний
робочий каталог, звідки починається наш пошук. Результатом виконання
find буде перелік імен усіх файлів та
каталогів у поточному робочому каталозі. Спочатку це може виглядати
безглуздо, але find має багато можливостей для фільтрації
результатів, і у цьому уроці ми розглянемо деякі з них.
Наприклад, опція -type d означає ‘обʼєкти, які є
каталогами’. Як і очікувалося, команда find виведе імена
п’яти каталогів (включно з .):
ВИХІД
.
./writing
./creatures
./animal-counts
./alkanes
Зверніть увагу, що об’єкти, які знаходить find, не
відсортовані. Якщо ми змінимо -type d на
-type f, натомість ми отримаємо список усіх файлів:
ВИХІД
./writing/LittleWomen.txt
./writing/haiku.txt
./creatures/basilisk.dat
./creatures/unicorn.dat
./creatures/minotaur.dat
./animal-counts/animals.csv
./numbers.txt
./alkanes/ethane.pdb
./alkanes/propane.pdb
./alkanes/octane.pdb
./alkanes/pentane.pdb
./alkanes/methane.pdb
./alkanes/cubane.pdb
Тепер спробуємо пошук за іменем:
ВИХІД
./numbers.txt
Ми очікували, що будуть знайдені усі текстові файли, але було
виведено лише ./numbers.txt. Проблема полягає у тому, що
оболонка розкриває символи підстановки, такі як *, ще
до виконання команд. Оскільки *.txt у поточному
каталозі розширюється до ./numbers.txt, то команда, яку ми
виконали, була такою:
Команда find зробила те, що ми просили; ми просто
попросили не те, що слід.
Щоб досягти потрібного результату, слід зробити так само, як і з
grep: візьмемо *.txt у лапки, щоб оболонка не
змогла розгорнути шаблон *. Таким чином, find
фактично отримає шаблон *.txt, а не ім’я файлу
numbers.txt:
ВИХІД
./writing/LittleWomen.txt
./writing/haiku.txt
./numbers.txt
Порівняння ls та
find
Обидві команди ls та find можна налаштувати
для виконання подібних завдань за допомогою відповідних опцій, але
зазвичай ls перелічує всі доступні елементи, тоді як, тоді
як find шукає обʼєкти з певними властивостями.
Як ми вже зазначали, потужність командного рядка полягає в об’єднанні
різних інструментів. Ми бачили, як цього досягти за допомогою каналів;
тепер розглянемо іншу методику. Як ми щойно бачили, команда
find . -name "*.txt" повертає список усіх текстових файлів
у поточному каталозі та його підкаталогах. Як ми можемо поєднати це з
wc -l, щоб порахувати кількість рядків в усіх цих
файлах?
Найпростіший спосіб - помістити команду find всередину
$():
ВИХІД
21022 ./writing/LittleWomen.txt
11 ./writing/haiku.txt
5 ./numbers.txt
21038 total
Коли термінал виконуватиме цю команду, він спочатку виконує все, що
знаходиться у виразі $(). Потім він замінить вираз
$() на результат виконання цієї команди. Оскільки
результатом команди find є три файли
./writing/LittleWomen.txt, ./writing/haiku.txt
та ./numbers.txt, термінал створює таку команду:
що є саме тим, що нам було потрібно. Це розширення працює так само,
як обробка шаблонів * та ? в оболонці, але
дозволяє нам використовувати будь-яку команду як власний “шаблон”.
Дуже поширено використовувати find та grep
разом. Перша команда знаходить файли, які відповідають заданому шаблону;
тоді як друга шукає в цих файлах рядки, що відповідають іншому шаблону.
Наприклад, ми можемо знайти txt-файли, які містять слово “searching”
шляхом пошуку рядка ‘searching’ у всіх файлах .txt
поточного каталогу:
ВИХІД
./writing/LittleWomen.txt:sitting on the top step, affected to be searching for her book, but was
./writing/haiku.txt:With searching comes loss
Порівняння та віднімання
Параметр -v із командою grep змінює логіку
зіставлення на протилежну, тому виводяться лише рядки, які не
відповідають шаблону. Враховуючи це, яка з наведених нижче команд знайде
всі файли .dat у каталозі creatures окрім
файлу unicorn.dat? Після того, як ви обміркуєте свою
відповідь, ви можете протестувати команди у каталогу
shell-lesson-data/exercise-data.
find creatures -name "*.dat" | grep -v unicornfind creatures -name *.dat | grep -v unicorngrep -v "unicorn" $(find creatures -name "*.dat")- Жоден із наведених вище варіантів.
Варіант 1 правильний. Взяття виразу шаблону у лапки запобігає
розгортанню його у терміналі та гарантує передачу безпосередньо команді
find.
Варіант 2 також працює у цьому випадку, оскільки термінал намагається
розгорнути *.dat, але у поточному каталозі немає файлів
*.dat, тому вираз із символами підстановки буде передано до
find. Вперше ми зіткнулися з цим у епізоді 3.
Варіант 3 є хибним, оскільки він переглядає вміст файлів у пошуках рядків, що не містять слово ‘unicorn’, замість фільтрації за іменами файлів.
Бінарні файли
Ми зосереджувалися виключно на пошуку шаблонів у текстових файлах. Але що робити, якщо ваші дані зберігаються у вигляді зображень, баз даних або в іншому форматі?
Існує декілька інструментів, які розширюють можливості
grep для роботи з деякими нетекстовими форматами. Проте
більш гнучкий підхід полягає в перетворенні даних у текст або вилучення
текстових елементів з даних. З одного боку, це полегшує виконання
простих завдань. З іншого боку, складні завдання зазвичай неможливо
виконати. Наприклад, досить легко написати програму, яка знаходить
розміри X і Y з файлів зображень для роботи з grep, але як
ви напишете щось для пошуку значень в електронній таблиці, клітинки якої
містять формули?
Останній варіант - усвідомити обмеження оболонки та обробки тексту і скористатися іншою мовою програмування. Коли прийде час це зробити, не будьте надто суворими до термінала. Багато сучасних мов програмування запозичили з нього багато ідей, а наслідування вважається найщирішою формою похвали.
Термінал Unix був створений ще до того, як народилась більшість його користувачів. Він проіснував так довго, тому що це одне з найпродуктивніших середовищ для програмування, які коли-небудь були створені - можливо, навіть саме найпродуктивніше. Хоча його синтаксис може здаватися незрозумілим, ті, хто його опанував, можуть експериментувати з різними командами в інтерактивному режимі, а потім використовувати набуті знання для автоматизації своїх завдань. Графічні інтерфейси користувача можуть бути простішими у використанні спочатку, але після опанування терміналу, продуктивність роботи в ньому стає неперевершеною. І, як писав Альфред Норт Уайтхед у 1911 році: ‘Цивілізація розвивається шляхом збільшення кількості важливих операцій, які ми можемо виконувати, не думаючи про них свідомо’.
Рекурсивно знаходить всі файли з розширенням
.datу поточному каталозіРахує кількість рядків у кожному з цих файлів
Сортує вивід з пункту 2. за числовим значенням
-
findшукає файли з певними властивостями, які відповідають шаблонам. -
grepфільтрує та повертає рядки з файлів, які відповідають заданим шаблонам. - Опція
--helpпідтримується багатьма командами bash та програмами, які можна виконати у bash, для отримання довідки щодо їх використання. -
man [команда]показує сторінку довідки для заданої команди. -
$([команда])виконує команду та заміняє вираз$()на результат її виконання.