Роббинс Арнольд
Шрифт:
Строки 52–58 являются главным циклом над нашими аргументами; строки 53–57 проверяют ошибки; когда они появляются, код выводит диагностическое сообщение и увеличивает значение переменной
errors
. Строки 60–64 являются частью эксперимента с
FTW_CHDIR
, выводящего начальный и конечный каталоги, если было использовано – с
. По-настоящему интересной функцией является
process
; это функция обратного вызова, которая обрабатывает каждый файл. Она использует базовый шаблон для функции обратного вызова nftw
, который является оператором switch
для значения flag
. 69 /* process --- выводит каждый файл на нужном уровне */
70
71 int process(const char "file, const struct stat *sb,
72 int flag, struct FTW *s)
73 {
74 int retval = 0;
75 const char *name = file + s->base;
76
77 printf("%*s", s->level * 4, ""); /* сделать отступ */
78
79 switch (flag) {
80 case FTW_F:
81 printf("%s (file)\n", name);
82 break;
83 case FTW_D:
84 printf("%s (directory)\n", name);
85 break;
86 case FTW_DNR:
87 printf("%s (unreadable directory)\n", name);
88 break;
89 case FTW_SL:
90 printf("%s (symbolic link)\n", name);
91 break;
92 case FTW_NS:
93 printf("%s (stat failed): %s\n", name, strerror(errno));
94 break;
95 case FTW_DP:
96 case FTW_SLN:
97 printf("%s: FTW_DP or FTW_SLN: can't happen'\n", name);
98 retval = 1;
99 break;
100 default:
101 printf("%s: unknown flag %d: can't happen'\n", name, flag);
102 retval = 1;
103 break;
104 }
105
106 return retval;
107 }
Строка 75 использует '
file + s->base
' для получения имени из полного пути. Это значение указателя сохраняется в переменной name
для повторного использования в функции. Строка 77 делает отступ нужного размера, используя красивый трюк. Используя
%*s
, printf
получает от первого аргумента ширину поля. Это вычисляется динамически как 'level * 4
'. Строка, которая должна быть выведена — «», пустая строка. Конечным результатом является то, что printf
создает для нас отступ нужного размера без необходимости запуска цикла. Строки 79–104 являются оператором
switch
. В данном случае он не делает ничего весьма интересного, кроме вывода имени файла и его типа (файл, каталог и т.д.) Хотя эта программа не использует
struct stat
, должно быть ясно, что вы могли бы сделать в функции обратного вызова все, что хотите. ЗАМЕЧАНИЕ. Джим Мейеринг (Jim Meyering), сопроводитель GNU Coreutils, замечает, что дизайн
nftw
несовершенен из-за ее рекурсивной природы. (Она рекурсивно вызывает себя при обработке подкаталогов.) Если иерархия каталогов становится действительно глубокой, в диапазоне уровней 20 000–40 000 (!), nftw
может выйти за пределы размера стека, уничтожив программу. Есть также и другие проблемы, связанные с дизайном nftw
. Версия GNU Coreutils после 5.0 исправляет это путем использования набора процедур fts
(см. fts(3)). 8.5. Обход дерева файлов: GNU
du
GNU версия
du
в GNU Coreutils использует nftw
для обхода одной или более иерархии файлов, собирая и выводя сведения, касающиеся количества используемого дискового пространства. У нее большое число опций, которые управляют ее поведением но отношению к символическим ссылкам, форматом вывода чисел и т.д. Это делает разбор кода труднее, чем могло бы быть при более простой версии. (Однако, мы не собираемся позволить этому остановить нас.) Вот сводка опций du
, которые вскоре будут полезны, когда мы рассмотрим код. $ du --help
Usage: du [OPTION]... [FILE]...
Дает сводку использования диска для каждого FILE,
рекурсивно для каталогов.
Обязательные для длинных опций аргументы являются обязательными
также и для коротких опций.
– a, --all записать число всех файлов, а не только
каталогов
– -apparent-size вывести видимые размеры, а не использование