14.5.1. Використання подпроцесса
Найстаріший метод універсалізації передбачає запуск оболонки в якості дочірнього процесу і вказівка їй універсалізуватися файлові імена. Стандартна функція popen () (див. Розділ 10) спрощує цей метод - просто запустіть команду ls * .с за допомогою popen () і прочитайте результат. Цей підхід може здатися дещо спрощеним, але все ж він забезпечує переноситься рішення проблеми універсалізації (ось чому програми на кшталт Perl використовують його).
Нижче наведена програма, яка універсалізує всі аргументи і відображає всі збіги.
3: #include
4: #include
14.5.2. Внутрішня універсалізація
Якщо необхідно універсалізуватися кілька файлових імен, запуск декількох подоболочек за допомогою popen () буде неефективним. Функція glob () дозволяє універсалізувати імена файлів без запуску будь-яких подпроцессов, однак за рахунок збільшення складності і зниження переносимості. Незважаючи на те що виклик glob () описаний в стандарті POSIX.2, багато варіанти Unix досі його не підтримують.
int glob (const char * pattern, int flags,
int (* errfunc) (const char * epath, int eerrno), glob_t * pglob);
Перший параметр, pattern. визначає шаблон, якому повинні відповідати імена файлів. У ньому допускається застосування операцій універсалізації *. і []. а також необов'язково і
які трактуються так само, як в стандартних оболонках. Останній параметр вказує на структуру, яка заповнюється результатами універсалізації. Ця структура визначена наступним чином.
int gl_pathc; / * Кількість шляхів в gl_pathv * /
char ** gl_pathv; / * Список gl_pathc, відповідних іменам шляхів * /
int gl_offs; / * Простір, зарезервоване в gl_pathv для GLOB_DOOFFS * /
flags - це одне або кілька перерахованих нижче значень, об'єднаних за допомогою бітового "АБО".
Повертається в разі помилки (якщо функція не може прочитати зміст каталогу, наприклад, через проблеми з доступом).
Якщо шаблон відповідає імені каталогу, при поверненні до цього імені буде доданий символ /.
Зазвичай повертаються імена шляхів сортуються в алфавітному порядку. Якщо цей прапорець встановлений, вони не сортуються.
При установці перші рядки pglob-> gl_offs в повернутому списку імен шляхів залишаються порожніми. Це дозволяє використовувати glob () під час вибудовування ряду аргументів, які будуть передані прямо в execv ().
Якщо жодне з файлових імен не відповідає шаблоном, в якості єдиного збіги повертається сам шаблон (зазвичай не повертається жодного збігу). В обох випадках шаблон повертається, якщо він не містить операцій універсалізації.
pglob імовірно є дійсним результатом попереднього виклику glob (). і будь-які результати цього виклику додаються до результатів попереднього виклику. Це полегшує універсалізацію безлічі шаблонів.
Зазвичай якщо операції універсалізації передує символ \. вона сприймається як звичайний символ. Наприклад, шаблон а \ * зазвичай відповідає тільки файлу по імені а *. Якщо встановлюється GLOB_NOESCAPE. символ \ втрачає своє особливе значення, aa \ * відповідає будь-якому імені файлу, що починається з символів а \. В такому випадку імена а \. і a \ bcd будуть відповідати, але arachnid - немає, оскільки воно не містить \.
Більшість оболонок не дозволяють застосовувати операції універсалізації для файлових імен, що починаються з. (Запустіть ls * в своєму домашньому каталозі і порівняйте отримане з результатом ls - а.). Функція glob () зазвичай поводиться подібним чином, але GLOB_PERIOD дозволяє операціям універсалізації працювати з провідним символом. Значення GLOB_PERIOD в POSIX не визначене.
Багато оболонки (наслідуючи приклад csh) розгортають послідовності з фігурними дужками як альтернативи; наприклад, шаблон розгортається до a b. а шаблон a - до a ab ас. GLOB_BRACE уможливлює таку поведінку. Значення GLOB_BRACE в POSIX не визначене.
Діє подібно GLOB_NOCHECK за винятком того, що він додає шаблон до списку результатів тільки в тому випадку, якщо вона не містить спеціальних знаків. Значення GLOB_NOMAGIC в POSIX не визначене.
Включає розширення з тильдой, в якому
/ Розгортаються до шляху до домашнього каталогу поточного користувача, а
user - до шляху до домашнього каталогу користувача user. Значення GLOB_TILDE в POSIX не визначене.
Збігається тільки з каталогами, а не з іншими типами файлів. Значення GLOB_ONLYDIR в POSIX не визначене.
Часто glob () наштовхується на каталоги, до яких у процесу немає доступу, що викликає помилки. Хоча помилку можна якимось чином обробити, однак якщо glob () повертає помилку (GLOB_ERR), операцію універсалізації не можна перезапустити там, де попередня операція універсалізації зіткнулася з помилкою. Оскільки складно одночасно усувати помилки, що відбуваються під час виконання glob (). і завершувати універсалізацію, glob () дозволяє передати помилку в спеціально передбачену для цього функцію, яка визначається в третьому параметрі glob ().
Прототип цієї функції показаний нижче.
int globerr (const char * pathname, int globerrno);
Функції передається колійне ім'я, що викликало помилку, і значення errno. повернене одним із системних викликів opendir (). readdir () або stat (). Якщо функція помилки повертає величину більше нуля, glob () повертається з помилкою. В іншому випадку операція універсалізації триває.