Обход файловой системы с помощью fts(3)
У меня вопрос по fts(3)
, Я получаю ошибку сегментации всякий раз, когда я пытаюсь получить доступ к любым членам fts_children()
функция. Когда я читаю справочную страницу по адресу http://www.kernel.org/doc/man-pages/online/pages/man3/fts.3.html она утверждает, что заполняется сама после запуска функции чтения и возвращает связанный список связанных ссылок. сквозь link
поле в структуре. Я подозреваю, что child_function ничего не возвращает, но я чувствую, что это не совпадает с man-страницей. Должен ли я добавлять эти файлы в дочерний буфер, потому что я думал, что это делается автоматически? Мой код ниже, спасибо!
#include<stdlib.h>
#include<stdio.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fts.h>
#include<string.h>
int compare (const FTSENT**, const FTSENT**);
int main(int argc, char* const argv[])
{
FTS* file_system = NULL;
FTSENT* child = NULL;
FTSENT* parent = NULL;
FTSENT* temp = NULL;
file_system = fts_open(argv + 1,FTS_COMFOLLOW | FTS_NOCHDIR,&compare);
while( (parent = fts_read(file_system)) != NULL)
{
child = fts_children(file_system,0);
printf("%s\n", child->fts_path);
}
// while (child ->fts_link != NULL)
// child = child->fts_link;
fts_close(file_system);
return 0;
}
int compare(const FTSENT** one, const FTSENT** two){
return (strcmp((*one)->fts_name, (*two)->fts_name));
}
"test_fs.c" 43L, 1108C
2 ответа
Вам просто нужно добавить проверку NULL.
Вы можете захотеть
- добавить один для
file_system
- проверить аргументы командной строки
Добавить больше обработки ошибок:
fts_children()
функция возвращает указатель наFTSENT
структура, описывающая первую запись вNULL
прекращается связанный список файлов в каталоге, в случае успеха.fts_children()
функция может выйти из строя и установитьerrno
для любой из ошибок, которыеchdir()
,malloc()
,opendir()
,readdir()
, а такжеstat()
функции уточняют.
Обновление до нового вопроса (ов) в комментарии:
- Цикл while для обхода связанного списка был смещен (вне внешнего цикла?)
- Printf отображал только путь... не имя файла.
пока вы на это:
#include<stdlib.h>
#include<stdio.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fts.h>
#include<string.h>
#include<errno.h>
int compare (const FTSENT**, const FTSENT**);
int main(int argc, char* const argv[])
{
FTS* file_system = NULL;
FTSENT* child = NULL;
FTSENT* parent = NULL;
if (argc<2)
{
printf("Usage: %s <path-spec>\n", argv[0]);
exit(255);
}
file_system = fts_open(argv + 1,FTS_COMFOLLOW | FTS_NOCHDIR,&compare);
if (NULL != file_system)
{
while( (parent = fts_read(file_system)) != NULL)
{
child = fts_children(file_system,0);
if (errno != 0)
{
perror("fts_children");
}
while ((NULL != child)
&& (NULL != child->fts_link))
{
child = child->fts_link;
printf("%s%s\n", child->fts_path, child->fts_name);
}
}
fts_close(file_system);
}
return 0;
}
int compare(const FTSENT** one, const FTSENT** two)
{
return (strcmp((*one)->fts_name, (*two)->fts_name));
}
Пример выходного фрагмента:
./.profiles/sehe/.opera/icons/cache/g_0000
./.profiles/sehe/.opera/icons/cache/g_0000/opr00002.tmp
./.profiles/sehe/.opera/icons/cache/g_0000/opr00003.tmp
./.profiles/sehe/home/sehe/.mozilla
fts_children: Permission denied
./.vbox-sehe-ipc/lock
Если вас интересует только обход всех каталогов и файлов по указанному пути, просто несколько раз вызовите fts_read
,
Если вы хотите перебирать только поток, пример @ sehe можно переписать так:
#include<stdlib.h>
#include<stdio.h>
#include<sys/types.h>
#include<fts.h>
#include<string.h>
#include<errno.h>
int compare (const FTSENT**, const FTSENT**);
void indent (int i);
int main(int argc, char* const argv[])
{
FTS* file_system = NULL;
FTSENT *node, = NULL;
if (argc<2)
{
printf("Usage: %s <path-spec>\n", argv[0]);
exit(255);
}
file_system = fts_open(argv + 1,FTS_COMFOLLOW|FTS_NOCHDIR,&compare);
if (NULL != file_system)
{
while( (node = fts_read(file_system)) != NULL)
{
switch (node->fts_info)
{
case FTS_D :
case FTS_F :
case FTS_SL:
indent(node->fts_level);
printf("%s\n", node->fts_name);
break;
default:
break;
}
}
fts_close(file_system);
}
return 0;
}
int compare(const FTSENT** one, const FTSENT** two)
{
return (strcmp((*one)->fts_name, (*two)->fts_name));
}
void indent(int i)
{
for (; i > 0; i--)
printf(" ");
}
Когда вы запускаете его, он перебирает поток и перечисляет все файлы и каталоги в следующем порядке:
★ mkdir -p test/A/1 test/A/2 test/B/1 test/B/2
★ tree test
test
├── A
│ ├── 1
│ └── 2
└── B
├── 1
└── 2
★ ./fts test
test
A
1
2
B
1
2
Вызов fts_children
только если вы хотите получить список дочерних узлов определенного каталога. В этом случае вы должны позвонить fts_read
хотя бы один раз перед звонком fts_children
; иначе fts_children
будет возвращать только узлы, указанные в argv
параметр для fts_open
,