Форум программистов, компьютерный форум, киберфорум
C/С++ под Linux
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.65/75: Рейтинг темы: голосов - 75, средняя оценка - 4.65
go
Эксперт С++
3646 / 1378 / 243
Регистрация: 16.04.2009
Сообщений: 4,526

Перебор файлов в каталоге (включая вложенные каталоги)

01.03.2012, 18:07. Показов 14573. Ответов 13
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Добрый день. Столкнулся с такой проблемой.
Язык Си.
Как перебирать все файлы в каком-либо каталоге(включая вложенные каталоги)?
Как определить: есть ли доступ к данному вложенному каталогу или файлу на каждом шаге перебора?
0
Лучшие ответы (1)
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
01.03.2012, 18:07
Ответы с готовыми решениями:

[boost::filesystem] Как пройтись по каталогу, включая вложенные каталоги ?
Доброго времени суток. Нужно скопировать в вектор все файлы в каталоге, включая файлы, находящиеся во вложенных каталогах. ...

перебор файлов в каталоге
Привет всем. Пытаюсь осуществить перебор файлов в определенном каталоге: ...

Определение суммарного размера файлов в папке, включая вложенные папки
Смысл таков... Может кто то встречал класс с методом или свойством для того чтобы вывести количество байт занимаемой папкой со вложенными...

13
Почетный модератор
7393 / 2639 / 281
Регистрация: 29.07.2006
Сообщений: 13,696
01.03.2012, 18:11
Лучший ответ Сообщение было отмечено Памирыч как решение

Решение

Цитата Сообщение от go Посмотреть сообщение
Как перебирать все файлы в каком-либо каталоге
readdir, scandir
Цитата Сообщение от go Посмотреть сообщение
есть ли доступ к данному вложенному каталогу или файлу
access
2
go
Эксперт С++
3646 / 1378 / 243
Регистрация: 16.04.2009
Сообщений: 4,526
01.03.2012, 18:25  [ТС]
Цитата Сообщение от Vourhey Посмотреть сообщение
scandir
А во вложенные каталогах он тоже сам залезает?

Добавлено через 1 минуту
И что она будет делать, если к какому-то каталогу нет доступа?

Добавлено через 27 секунд
Цитата Сообщение от Vourhey Посмотреть сообщение
readdir,
Уже пробовал ее. Не получилось с ней обойти.
0
Эксперт С++
 Аватар для Nameless One
5828 / 3479 / 358
Регистрация: 08.02.2010
Сообщений: 7,448
01.03.2012, 18:40
Цитата Сообщение от go Посмотреть сообщение
А во вложенные каталогах он тоже сам залезает?
нет, просто вызывай ее рекурсивно для всех полученных каталогов из списка
Цитата Сообщение от go Посмотреть сообщение
И что она будет делать, если к какому-то каталогу нет доступа?
проверяй перед вызовом с помощью access
Цитата Сообщение от go Посмотреть сообщение
Уже пробовал ее. Не получилось с ней обойти.
где код?
1
Почетный модератор
7393 / 2639 / 281
Регистрация: 29.07.2006
Сообщений: 13,696
01.03.2012, 18:42
Цитата Сообщение от go Посмотреть сообщение
Уже пробовал ее. Не получилось с ней обойти.
А функция тут при чем? Все дело в тебе. Пиши тут код, скажут, где ошибка
0
Эксперт С++
 Аватар для Nameless One
5828 / 3479 / 358
Регистрация: 08.02.2010
Сообщений: 7,448
01.03.2012, 18:43
В книжке «UNIX. Профессиональное программирование» (У. Стивенс, С. Раго) есть отличный пример для рекурсивного обхода дерева каталогов в разделе 4.21. Можно сказать, там уже готовый код для твоей задачи.
1
go
Эксперт С++
3646 / 1378 / 243
Регистрация: 16.04.2009
Сообщений: 4,526
01.03.2012, 19:06  [ТС]
Цитата Сообщение от Nameless One Посмотреть сообщение
где код?
C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
#include <stdio.h>
#include <dirent.h>
#include <stdlib.h>
 
void cmp(DIR *, DIR *);
 
int main(int argc, char *argv[])
{
        DIR *d1, *d2;
        
        if ( !(d1 = opendir(argv[1])) || ! (d2 = opendir(argv[2])) || argc < 3 )
        {
                fprintf(stderr, "$s: error dir or arg\n", argv[0]);
                exit(1);
        }
 
        cmp(d1, d2);
 
        return 0;
}
 
void cmp(DIR *d1, DIR *d2)
{
        struct dirent *f1;
        struct dirent *f2;
        
        while ( (f1 = readdir(d1)) )
        {
                if ( f1->d_type == DT_DIR )
                {
                        DIR *t1;
                        if ( (t1 = opendir(f1->d_name)) )
                                cmp(t1, d2);
                }
                else
                {
                        while ( (f2 = readdir(d2)) )
                        {
                                if ( f2->d_type == DT_DIR )
                                {
                                        DIR *t2;
                                        if ( (t2 = opendir(f2->d_name)) )
                                                cmp(d1, t2);
                                }
                                else
                                        printf("%s - %s\n", f1->d_name, f2->d_name);
                        }
                }
        }   
}
Перебираю для сравнения в двух каталогах

Добавлено через 25 секунд

Не по теме:

Цитата Сообщение от Vourhey Посмотреть сообщение
Все дело в тебе.
ну это ясно ведь ;)



Добавлено через 11 минут
Nameless One, в книге
C
1
2
3
4
5
struct dirent {
ino_t d_ino; /* номер индексного узла */
char d_name[NAME_MAX +1]; /* строка имени файла, завершающаяся */
/* нулевым символом */
}
http://www.delorie.com/gnu/doc... c_270.html здесь иначе написано или нет(или я не правильно перевел)?
0
Эксперт С++
 Аватар для Nameless One
5828 / 3479 / 358
Регистрация: 08.02.2010
Сообщений: 7,448
02.03.2012, 07:17
Цитата Сообщение от go Посмотреть сообщение
Nameless One, в книге...
в книге описаны только те поля, которые обязательно должны присутствовать в структуре (то же самое пишет и "man dirent.h", "man 3 readdir" добавляет еще три поля). Конкретная реализация может добавлять дополнительные поля.

Вот набросал функцию обхода дерева каталогов:
C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
#include <stdio.h>
#include <stdlib.h>
#include <dirent.h>
#include <limits.h>
#include <string.h>
#include <sys/stat.h>
 
typedef int           /* 1 в случае ошибки, 0 в прот. случае */
(*PFUNC)(const char*,         /* обрабатываемый файл */
     const struct stat*); /* информация о файле */
 
int             /* 1 в случае ошибки, 0 в прот. случае */
walk(const char*,       /* начальная директория */
     PFUNC,         /* функция, которая вызывается для каждого
                   элемента директории */
     int);          /* вызывать функцию для каталогов? */
 
int print_entry(const char* name, const struct stat* st)
{
    printf("%s%s\n", name,
       /* добавляем "/" к именам каталогов при выводе
        * для наглядности
        */
       (S_ISDIR(st->st_mode) ? "/" : ""));
 
    return 0;
}
 
int main(int argc, char* argv[])
{
    if(argc != 2)
    {
    fprintf(stderr, "Usage: %s DIR\n", argv[0]);
    exit(1);
    }
 
    /* печать всего дерева каталогов, начиная
     * с argv[1] (каталоги тоже печатаются)
     */
    exit(walk(argv[1], print_entry, 1));
}
 
/* делаем глобальной переменной, чтобы не допустить разрастания
 * стека при рекурсивных вызовах (рекурсия-то древовидная)
 */
char buf[PATH_MAX];
 
int walk(const char* dirname, PFUNC pfunc, int do_dirs)
{
    DIR* dp;
    struct stat st;
    struct dirent* dirp;
    int retval = 0;
 
    size_t len = strlen(dirname);
 
    if((dp = opendir(dirname)) == NULL)
    {
    perror(dirname);
    return 1;
    }
 
    strncpy(buf, dirname, len);
 
    while((dirp = readdir(dp)) != NULL)
    {
    if(strcmp(dirp->d_name, ".") == 0 ||
       strcmp(dirp->d_name, "..") == 0)
        continue;
 
    buf[len] = '/';
    buf[len+1] = '\0';
 
    strcat(buf, dirp->d_name);
    
    if(lstat(buf, &st) == -1)
    {
        perror(dirp->d_name);
        retval = 1;
        break;
    }
 
    if(S_ISDIR(st.st_mode))
    {
        if(do_dirs)
        {
        if(pfunc(buf, &st) == 1)
        {
            retval = 1;
            break;
        }
        }
                
        if(walk(buf, pfunc, do_dirs) == 1)
        {
        retval = 1;
        break;
        }
        
    }
    else if(pfunc(dirp->d_name, &st) == 1)
    {
        retval = 1;
        break;
    }
 
    buf[len] = '\0';
    }
 
    closedir(dp);
    return retval;
}
2
go
Эксперт С++
3646 / 1378 / 243
Регистрация: 16.04.2009
Сообщений: 4,526
04.03.2012, 13:43  [ТС]
Цитата Сообщение от Nameless One Посмотреть сообщение
int walk(const char* dirname, PFUNC pfunc, int do_dirs)
Для чего необходим третий аргумент?
0
Эксперт С++
 Аватар для Nameless One
5828 / 3479 / 358
Регистрация: 08.02.2010
Сообщений: 7,448
04.03.2012, 14:11
go, он указывает что нужно вызывать функцию pfunc не только для обычных файлов, но и для каталогов.
Т.е., пусть у нас есть такое дерево каталогов:
Code
1
2
3
4
5
6
7
8
9
10
11
12
13
[nameless@desktop tree]$ tree . -F --charset HTML
.
|-- topdir1/
|   |-- file
|   `-- subdir/
|       `-- file
`-- topdir2/
    |-- file
    `-- subdir/
        `-- file
 
4 directories, 4 files
[nameless@desktop tree]$
Обходим текущий "." каталог. Если параметр do_dirs равен нулю, то мы обрабатываем только файлы в дереве каталогов, т.е. функция будет вызвана только для всех file. Если же он ненулевой, то в дополнении к файлам функция будет вызвана для всех подкаталогов: topdir1, topdir2, topdir1/subdir, topdir2/subdir.

А вообще, почему бы не запустить эту функцию самому с разными значениями этого параметра? Быстро и наглядно.
1
1259 / 650 / 44
Регистрация: 06.02.2011
Сообщений: 1,654
04.03.2012, 17:06
Nameless One, простите, но глаза режет
C
1
2
3
4
        buf[len] = '/';
        buf[len+1] = '\0';
 
        strcat(buf, dirp->d_name);
2TC: за Вас уже все написали man ftw
0
Эксперт С++
 Аватар для Nameless One
5828 / 3479 / 358
Регистрация: 08.02.2010
Сообщений: 7,448
04.03.2012, 17:10
g_u_e_s_t, и это даже не мой код, а немного переработанный пример из книги, хотя соглашусь, выглядит кривовато
0
go
Эксперт С++
3646 / 1378 / 243
Регистрация: 16.04.2009
Сообщений: 4,526
06.03.2012, 19:56  [ТС]
Цитата Сообщение от Nameless One Посмотреть сообщение
if(strcmp(dirp->d_name, ".") == 0 ||
* * * * * *strcmp(dirp->d_name, "..") == 0)
Я так понимаю это пропуск текущего каталога. Не могли бы Вы объяснить, когда может возникнуть в этом необходимость? Ума не приложу для чего это.
0
Эксперт С++
 Аватар для Nameless One
5828 / 3479 / 358
Регистрация: 08.02.2010
Сообщений: 7,448
07.03.2012, 11:48
go, "." и ".." обозначают текущий и родительский каталоги, соответственно. Очевидно, что нет смысла вызывать рекурсивную обработку текущего каталога, т.к. его элементы уже обрабатываются в данный момент в данном рекурсивном вызове. Также очевидно, что обрабатывать родительский каталог тоже не нужно.
1
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
07.03.2012, 11:48
Помогаю со студенческими работами здесь

Поиск количества однотипных файлов в директории включая вложенные папки
Доброго времени суток, подскажите пожалуйста, каким образом можно реализовать поиск количества однотипных файлов в директорие так чтобы...

Вывод списка исполняемых файлов (включая информацию о файлах) в заданном каталоге
Разработать прикладную программу, осуществляющую выявление по содержимому в заданном каталоге на диске ПК всех исполняемых файлов и вывод...

Перебор циклом файлов в каталоге
Доброго времени суток. Как пройтись циклом по файлам в папке?

Перебор файлов в каталоге - групповое редактирование
Есть файлы такого типа Расположены они к примеру с:\temp 1 файл.xls 2 файл.xls 3 файл.xls 4 файл.xls 5 файл.xls Как мне их...

Перебор в цикле с FOR файлов в каталоге с русским именем
Команда перебора файлов не проходит set Chain = D:\seva\Отдел ИО\Работы\Программы for %%A in (&quot;%Chain%\*.txt&quot;) do (echo...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
14
Ответ Создать тему
Новые блоги и статьи
Отправка уведомления на почту при изменении наименования справочника
Maks 24.03.2026
Программная отправка письма электронной почты на примере изменения наименования справочника "Склады" в конфигурации БП3. Перед реализацией необходимо выполнить настройку системной учетной записи. . .
модель ЗдравоСохранения 5. Меньше увольнений- больше дохода!
anaschu 24.03.2026
Теперь система здравосохранения уменьшает количество увольнений. 9TO2GP2bpX4 a42b81fb172ffc12ca589c7898261ccb/ https:/ / rutube. ru/ video/ a42b81fb172ffc12ca589c7898261ccb/ Слева синяя линия -. . .
Midnight Chicago Blues
kumehtar 24.03.2026
Такой Midnight Chicago Blues, знаешь?. . Когда вечерние улицы становятся ночными, а ты не можешь уснуть. Ты идёшь в любимый старый бар, и бармен наливает тебе виски. Ты смотришь на пролетающие. . .
Контроль уникальности заводского номера - вариант №2
Maks 24.03.2026
В отличие от предыдущего варианта добавлено прерывание циклов, также добавлены новые переменные для сохранения контекста ошибки перед прерыванием цикла: Процедура ПередЗаписью(Отказ, РежимЗаписи,. . .
SDL3 для Desktop (MinGW): Вывод текста со шрифтом TTF с помощью библиотеки SDL3_ttf на Си и C++
8Observer8 24.03.2026
Содержание блога Финальные проекты на Си и на C++: finish-text-sdl3-c. zip finish-text-sdl3-cpp. zip
Жизнь в неопределённости
kumehtar 23.03.2026
Жизнь — это постоянное существование в неопределённости. Например, даже если у тебя есть список дел, невозможно дойти до точки, где всё окончательно завершено и больше ничего не осталось. В принципе,. . .
Модель здравоСохранения: работники работают быстрее после её введения.
anaschu 23.03.2026
geJalZw1fLo Корпорация до введения программа здравоохранения имела много невыполненных работниками заданий, после введения программы количество заданий выросло. Но на выплатах по больничным это. . .
Контроль уникальности заводского номера - вариант №1
Maks 23.03.2026
Алгоритм контроля уникальности заводского (или серийного) номера на примере документа выдачи шин для спецтехники с табличной частью в конфигурации КА2. Данные берутся из регистра сведений, по. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru