Самый старый метод универсализации предусматривает запуск оболочки в качестве дочернего процесса и указание ей универсализировать файловые имена. Стандартная функция popen()
(см. главу 10) упрощает этот метод — просто запустите команду ls *.с
с помощью popen()
и прочитайте результат. Этот подход может показаться несколько упрощенным, но все же он обеспечивает переносимое решение проблемы универсализации (вот почему приложения вроде Perl используют его).
Ниже приведена программа, которая универсализирует все аргументы и отображает все совпадения.
1: /* popenglob.c */
2:
3: #include <stdio.h>
4: #include <string.h>
5: #include <sys/wait.h>
6: #include <unistd.h>
7:
8: int main(int argc, const char ** argv)
9: char buf[1024];
10: FILE * ls;
11: int result;
12: int i;
13:
14: strcpy(buf, 'ls');
15:
16: for (i = 1; i < argc; i++) {
17: strcat(buf, argv[i]);
18: strcat(buf, ' ');
19: }
20:
21: ls = popen(buf, 'r');
22: if (!ls) {
23: perror('popen');
24: return 1;
25: }
26:
27: while (fgets(buf, sizeof(buf), ls))
28: printf('%s', buf);
29:
30: result = pclose(ls);
31:
32: if (!WIFEXITED(result)) return 1;
33:
34: return 0;
35: }
14.5.2. Внутренняя универсализация
Если необходимо универсализировать несколько файловых имен, запуск нескольких подоболочек с помощью popen()
будет неэффективным. Функция glob()
позволяет универсализировать имена файлов без запуска каких-либо подпроцессов, однако за счет увеличения сложности и снижения переносимости. Несмотря на то что вызов glob()
описан в стандарте POSIX.2, многие варианты Unix до сих пор его не поддерживают.
#include <glob.h>
int glob(const char * pattern, int flags,
int (*errfunc)(const char * epath, int eerrno), glob_t* pglob);
Первый параметр, pattern
, определяет шаблон, которому должны соответствовать имена файлов. В нем допускается применение операций универсализации *
, ?
и []
, а также необязательно {
, }
и ~
которые трактуются так же, как в стандартных оболочках. Последний параметр указывает на структуру, которая заполняется результатами универсализации. Эта структура определена следующим образом.
#include <glob.h>
typedef struct {
int gl_pathc; /* количество путей в gl_pathv */
char **gl_pathv; /* список gl_pathc, соответствующих именам путей */
int gl_offs; /* пространство, зарезервированное в gl_pathv для GLOB_DOOFFS*/
} glob_t;
flags
— это одно или несколько перечисленных ниже значений, объединенных с помощью битового 'ИЛИ'.
GLOB_ERR | Возвращается в случае ошибки (если функция не может прочесть оглавление каталога, например, из-за проблем с доступом). |
GLOB_MARK | Если шаблон соответствует имени каталога, при возврате к этому имени будет добавлен символ / . |
GLOB_NOSORT | Обычно возвращаемые имена путей сортируются в алфавитном порядке. Если этот флаг установлен, они не сортируются. |
GLOB_DOOFFS | При установке первые строки pglob->gl_offs в возвращаемом списке имен путей оставляются пустыми. Это позволяет использовать glob() во время выстраивания ряда аргументов, которые будут переданы прямо в execv() . |
GLOB_NOCHECK | Если ни одно из файловых имен не соответствует шаблону, в качестве единственного совпадения возвращается сам шаблон (обычно не возвращается ни одного совпадения). В обоих случаях шаблон возвращается, если он не содержит операций универсализации. |