Як використовувати Pipes в Linux

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

Канали: Основа командного рядка

Канали є невід’ємною частиною операційних систем Linux та Unix, вони присутні практично в кожному посібнику або статті про командний рядок. Їх важливість важко переоцінити. Навіть при перегляді наших попередніх публікацій, ви неодмінно знайдете приклади їх використання.

Завдяки філософії Linux, яка полягає у створенні невеликих, спеціалізованих інструментів, кожен з яких виконує свою функцію на відмінно, канали дозволяють вам використовувати ці інструменти разом. Замість однієї складної команди, ви збираєте “команду мрії” з невеликих утиліт, де вихід однієї стає входом для іншої.

Простий приклад: Пошук файлів

Розглянемо приклад: ви хочете підрахувати, скільки файлів певного типу знаходиться у вашому каталозі. Хоча є декілька способів зробити це, ми використаємо канали, щоб продемонструвати їхню силу.

Першим кроком є отримання списку файлів за допомогою команди ls:

ls

Далі, ми хочемо відфільтрувати файли, використовуючи grep. Припустимо, нас цікавлять файли, у назві яких є слово “сторінка”.

Символ | передає вихід команди ls до grep:

ls | grep "page"

Команда grep виводить лише ті рядки, які відповідають заданому шаблону, залишаючи нам лише файли, що містять слово “page”.

У цьому простому прикладі ми бачимо, як вихід однієї команди (ls) стає вхідними даними для іншої (grep). Результат, який ми бачимо на екрані, є результатом роботи команди grep.

Розширюємо наш ланцюжок

Тепер давайте додамо ще одну команду до нашого ланцюжка. Ми можемо підрахувати кількість файлів, додавши команду wc з опцією -l (кількість рядків). Для точності, додамо також опцію -l (довгий формат) до ls.

ls -l | grep "page" | wc -l

Тепер команда grep не є останньою в ланцюжку, і ми бачимо результат роботи команди wc, яка підраховує кількість файлів “сторінка” у каталозі (у цьому випадку 69).

Давайте замінимо wc на awk. Використовуючи awk, ми можемо вивести стовпці 5, 3 і 9 з виводу команди ls -l (розмір, власник і назву файлу):

ls -l | grep "page" | awk '{print $5 " " $3 " " $9}'

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

Додамо сортування за розміром файлу:

ls -l | grep "page" | awk '{print $5 " " $3 " " $9}' | sort -n

Тепер вихід відсортовано за розміром файлу.

Фільтрація результатів за допомогою tail

Наостанок, давайте виведемо лише останні 5 рядків, використовуючи команду tail -5:

ls -l | grep "page" | awk '{print $5 " " $3 " " $9}' | sort -n | tail -5

Отже, команда тепер видає нам 5 найбільших файлів “.page” у каталозі, відсортованих за розміром. Ми створили власну команду, поєднуючи прості утиліти за допомогою каналів.

Ми можемо легко змінити порядок сортування, використовуючи sort -nr, а також відобразити перші 5 рядків, використовуючи head -5.

Додаткові приклади

Розглянемо ще декілька корисних прикладів. Наприклад, команда xargs дозволяє передавати вихід інших команд як аргументи до іншої команди. Ось як можна підрахувати слова, символи та рядки у всіх файлах .page:

ls *.page | xargs wc

Ось приклад отримання списку унікальних розширень файлів з кількістю кожного типу:

ls | rev | cut -d'.' -f1 | rev | sort | uniq -c

Тут відбувається наступне:
ls: виводить список файлів.
rev: перевертає текст імен файлів.
cut: обрізає текст по першому символу ..
rev: знову перевертає текст, отримуючи розширення файлу.
sort: сортує список розширень.
uniq: підраховує кількість кожного унікального розширення.

Результат: відсортований список розширень файлів з кількістю кожного.

Іменовані канали

Існує також інший тип каналів – іменовані канали. Звичайні канали створюються оболонкою під час виконання команди, існують лише під час її виконання. Іменовані канали є постійними об’єктами у файловій системі, вони можуть бути використані для взаємодії між різними процесами.

Іменовані канали можна створити за допомогою команди mkfifo. Спробуємо створити канал під назвою “geek-pipe”:

mkfifo geek-pipe

Використовуючи команду ls -l, ми можемо побачити, що це об’єкт файлової системи типу “p” (pipe):

ls -l geek-pipe

Використання іменованого каналу

На відміну від звичайних каналів, іменований канал утримує дані, поки вони не будуть прочитані. Для цього прикладу нам знадобиться два термінали.

# Terminal-1

в першому вікні термінала і

# Terminal-2

в другому.

В першому терміналі передамо результат команди в іменований канал:

ls | rev | cut -d'.' -f1 | rev | sort | uniq -c > geek-pipe

Після виконання цієї команди дані відобразяться в другому терміналі.

І в першому терміналі ви знову побачите командний рядок.

Отже, ми:

Перенаправили вихід в іменований канал.
Перший термінал чекав на зчитування даних.
Дані були зчитані з іменованого каналу у другому терміналі.
Перший термінал знову отримав командний рядок.

Звичайно, можна запустити команду в першому терміналі у фоновому режимі (&), але суть прикладу в тому, щоб підкреслити блокуючу природу іменованого каналу.

Сила каналів

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

Порада наостанок: створюйте свої команди поступово, додаючи по одній команді за раз, перевіряючи результат на кожному етапі.