C как получить список файлов в каталоге

Обновлено: 06.07.2024

Как определить список файлов в каталоге из моего кода C или C++?

Мне не разрешено выполнять команду ls и анализировать результаты из моей программы.

В небольших и простых задачах я не использую boost, я использую dirent.h, который также доступен для windows:

Это всего лишь небольшой заголовочный файл, который выполняет большинство простых задач без использования большого подхода на основе шаблонов, такого как boost (без обид, мне нравится boost!).

Автор слоя совместимости окон - Тони Ронкко. В Unix это стандартный заголовок.

ОБНОВЛЕНИЕ 2017:

В С++ 17 теперь есть официальный способ перечисления файлов вашей файловой системы: std::filesystem . Ниже приведен отличный ответ от Shreevardhan с этим исходным кодом:

С++ 17 теперь имеет std::filesystem::directory_iterator , который можно использовать как

К сожалению, стандарт C++ не определяет стандартный способ работы с файлами и папками таким образом.

Поскольку кроссплатформенного способа не существует, лучшим кроссплатформенным способом является использование библиотеки, такой как модуль файловой системы boost.

Кроссплатформенный метод повышения:

Следующая функция, учитывая путь к каталогу и имя файла, рекурсивно ищет в каталоге и его подкаталогах имя файла, возвращая bool, а в случае успеха - путь к найденному файлу.

Источник со страницы поддержки, упомянутой выше.

Для систем на основе Unix/Linux:

Пример кода, который ищет в каталоге запись "name":

Исходный код с указанных выше страниц руководства.

Для систем на базе Windows:

Вы можете использовать функции Wina API FindFirstFile/FindNextFile/FindClose.

В следующем примере C++ показано минимальное использование FindFirstFile.

Исходный код с указанных выше страниц MSDN.

Одной функции достаточно, вам не нужно использовать стороннюю библиотеку (для Windows).

PS: как упоминалось @Sebastian, вы можете изменить *.* на *.ext , чтобы получить только EXT файлы (т.е. определенного типа) в этом каталоге.

Для решения только C, пожалуйста, проверьте это. Для этого требуется только дополнительный заголовок:

Некоторые преимущества перед другими вариантами:

  • Он переносится - обертывает POSIX dirent и Windows FindFirstFile
  • Он использует readdir_r где доступно, что означает, что он (обычно) threadsafe
  • Поддерживает Windows UTF-16 через те же макросы UNICODE
  • Это C90, поэтому даже очень древние компиляторы могут его использовать

Я рекомендую использовать glob с помощью этой многоразовой обертки. Он генерирует vector<string> , соответствующий пути файла, которые соответствуют шаблону glob:

который затем может быть вызван с обычным шаблоном шаблона системы, например:

Вот очень простой код в C++11 с использованием библиотеки boost::filesystem для получения имен файлов в каталоге (исключая имена папок):

Почему бы не использовать glob() ?

Я думаю, ниже фрагмента можно использовать список всех файлов.

Ниже приведена структура struct dirent

Попробуйте повысить для x-платформенного метода

или просто используйте файлы вашего конкретного файла.

Проверьте этот класс, который использует win32 api. Просто создайте экземпляр, предоставив foldername , из которого вы хотите распечатать, затем вызовите метод getNextFile , чтобы получить следующий filename из каталога. Я думаю, что ему нужны windows.h и stdio.h .

Кроме того, иногда хорошо идти прямо к источнику (каламбур). Вы можете многому научиться, глядя на внутренности некоторых из наиболее распространенных команд в Linux. Я создал простое зеркало GNU coreutils на github (для чтения).

Возможно, это не относится к Windows, но при использовании этих методов можно использовать несколько вариантов использования Unix-вариантов.

Надеюсь, что это поможет.

Я надеюсь, что этот код поможет вам.

Ответ Shreevardhan отлично работает. Но если вы хотите использовать его в С++ 14, просто создайте namespace fs = experimental::filesystem; изменений namespace fs = experimental::filesystem;

Эта реализация реализует вашу цель, динамически заполняя массив строк содержимым указанного каталога.

Это работает для меня. Извините, если я не могу вспомнить источник. Вероятно, это с man-страницы.

вы можете получить все прямые файлы в корневом каталоге, используя std :: experimental :: filesystem :: directory_iterator(). Затем прочитайте имя этих файлов путей.

Этот ответ должен работать для пользователей Windows, которым не удалось получить эту работу с Visual Studio с любыми другими ответами.

Загрузите файл dirent.h с страницы github. Но лучше просто использовать файл Raw dirent.h и следовать моим шагам ниже (это то, как я получил его на работу).

Перейдите в свой проект и добавьте новый элемент ( Ctrl + Shift + A ). Добавьте файл заголовка (.h) и назовите его dirent.h.

Вставьте код Raw dirent.h в свой заголовок.

Включите "dirent.h" в свой код.

Поместите в свой код метод void filefinder() и вызовите его из main функции или отредактируйте функцию, как вы хотите ее использовать.

Затем просто прочитайте файл.

EDIT: этот ответ следует считать взломом, но он действительно работает (хотя и определенно на платформе), если у вас нет доступа к более элегантным решениям.

Поскольку файлы и вспомогательные каталоги каталога обычно хранятся в древовидной структуре, интуитивно понятным способом является использование алгоритма DFS для рекурсивного прохождения каждого из них. Вот пример в операционной системе Windows, используя основные функции файла в io.h. Вы можете заменить эти функции на другой платформе. Я хочу выразить, что основная идея DFS отлично справляется с этой проблемой.

Я попытался следовать примеру, указанному в обоих ответах, и, возможно, стоит отметить, что он выглядит так, как если бы std::filesystem::directory_entry была изменена, чтобы не иметь перегрузки оператора << . Вместо std::cout << p << std::endl; Я должен был использовать следующее, чтобы иметь возможность компилировать и заставить его работать:

пытаясь передать p самостоятельно, std::cout << привела к отсутствию ошибки перегрузки.

Просто то, что я хочу поделиться, и поблагодарить вас за материал для чтения. Поиграйте с функцией, чтобы понять ее. Вам это может понравиться. e стоял за расширение, p для пути, а s - для разделителя пути.

Если путь передается без окончания разделителя, разделитель будет добавлен к пути. Для расширения, если вводится пустая строка, функция возвращает любой файл, который не имеет расширения в своем имени. Если была введена одна звезда, все файлы в каталоге будут возвращены. Если длина e больше 0, но не одна *, то точка будет добавлена к e, если e не содержала точку в нулевой позиции.

Для возвращаемого значения. Если возвращается карта нулевой длины, ничего не было найдено, но каталог был открыт нормально. Если индекс 999 доступен из возвращаемого значения, но размер карты равен только 1, это означает, что возникла проблема с открытием пути к каталогу.

Обратите внимание, что для эффективности эта функция может быть разделена на 3 функции меньшего размера. Кроме того, вы можете создать функцию вызывающего абонента, которая будет определять, какую функцию он будет вызывать на основе ввода. Почему это более эффективно? Говоря, что если вы собираетесь захватить все, что является файлом, делая этот метод, подфункция, созданная для захвата всех файлов, будет просто захватывать все файлы и не нужно оценивать какое-либо другое ненужное условие каждый раз, когда он находит файл.

Это также относится к тому, когда вы захватываете файлы, у которых нет расширения. Специальная встроенная функция для этой цели будет оценивать только погоду, если найденный объект является файлом, а затем, есть ли имя файла в нем.

Сохранение может быть не очень большим, если вы читаете только каталоги с не так большим количеством файлов. Но если вы читаете массовое количество каталогов, или если в каталоге есть несколько сотен тысяч файлов, это может быть огромной экономией.

мне не разрешено выполнять ls команда и анализ результатов из моей программы.

в небольших и простых задачах я не использую boost, я использую dirent.h, который также доступен для Windows:

Это просто небольшой файл заголовка и делает большинство простых вещей, которые вам нужны, не используя большой подход на основе шаблонов, как boost(не обижайтесь, мне нравится boost!).

автором уровня совместимости windows является Тони Ронкко. В Unix, это стандартный заголовок.

обновление 2017:

В C++17 есть теперь это официальный способ перечислить файлы вашей файловой системы: std::filesystem . Есть отличный ответ от Shreevardhan ниже с этим исходным кодом:

рассмотрите возможность повышения его ответа, если вы используете подход C++17.

к сожалению, стандарт C++ не определяет стандартный способ работы с файлами и папками в эту сторону.

поскольку нет кросс-платформенного способа, лучший кросс-платформенный способ-использовать библиотеку, такую как модуль файловой системы boost.

кросс-платформенный метод повышения:

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

источник со страницы boost, упомянутой выше.

для систем на базе Unix / Linux:

пример кода, который ищет каталог для записи "имя":

исходный код из вышеуказанных страниц.

для систем на базе windows:

вы можете использовать Win32 API FindFirstFile / findnextfile функция / FindClose функции.

в следующем примере C++ показано минимальное использование FindFirstFile.

исходный код с вышеуказанных страниц msdn.

C++17 теперь имеет std::filesystem::directory_iterator , который можно использовать как

достаточно одной функции, вам не нужно использовать стороннюю библиотеку (для Windows).

PS: Как упоминалось @Sebastian, вы можете изменить *.* to *.ext чтобы получить только EXT-файлы (т. е. определенного типа) в этом каталоге.

для решения только C, пожалуйста, проверьте это. Для этого требуется только дополнительный заголовок:

некоторые преимущества перед другими вариантами:

  • это портативный-обертывания POSIX dirent и Windows FindFirstFile
  • он использует readdir_r где доступно, что означает, что это (обычно) threadsafe
  • поддерживает Windows UTF-16 через то же самое UNICODE макрос
  • это C90 так что даже очень древние компиляторы могут использовать его

Я рекомендую использовать glob С этой оболочкой многоразовые. Он генерирует vector<string> соответствующие пути к файлам, которые соответствуют шаблону glob:

что тогда можно назвать нормальным шаблону системы, такие как:

вот очень простой код C++11 используя boost::filesystem библиотека для получения имен файлов в каталоге (за исключением имен папок):

почему бы не использовать glob() ?

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

Ниже приведена структура структуры dirent

попробуйте boost для метода x-platform

или просто используйте свой конкретный файл для ОС.

проверьте этот класс, который использует win32 api. Просто создайте экземпляр, предоставив foldername из которого вы хотите список, то вызов getNextFile метод, чтобы получить следующий filename из каталога. Я думаю, что это нужно windows.h и stdio.h .

руководство GNU FTW

кроме того, иногда это хорошо, чтобы пойти прямо к источнику (каламбур). Вы можете многому научиться, глядя на внутренности некоторых наиболее часто используемые команды в Linux. Я установил простое зеркало coreutils GNU на github (для чтение.)

возможно, это не относится к Windows, но ряд случаев использования вариантов Unix может быть с помощью этих методов.

надеюсь, это поможет.

Я надеюсь, что этот код поможет вам.

эта реализация реализует вашу цель, динамически заполняя массив строк содержимым указанного каталога.

это работает для меня. Простите, если не могу вспомнить источник. Вероятно, это с мужской страницы.

Shreevardhan ответ работает отлично. Но если вы хотите использовать его в C++14 просто внести изменения namespace fs = experimental::filesystem;

вы можете получить все прямые файлы в корневом каталоге с помощью std:: experimental::filesystem:: directory_iterator(). Затем прочитайте название этих pathfiles.

тогда просто прочитайте файл.

EDIT: этот ответ следует рассматривать как взлом, но он действительно работает (хотя и определенным образом), если у вас нет доступа к более элегантным решениям.

этот ответ должен работать для пользователей Windows, у которых возникли проблемы с этой работой с Visual Studio с любым другим ответом.

скачать dirent.H файл со страницы github. Но лучше просто использовать Raw dirent.H файл и выполните мои шаги ниже (это то, как я получил его на работу).

страница Github для dirent.h для Windows:страница Github для dirent.h

перейдите в свой проект и добавьте новый элемент ( Ctrl + Shift + A ). Добавить файл заголовка (.h) и назовите его dirent.h.

вставить Raw dirent.файл H код в заголовок.

включить " dirent.h " в вашем коде.

поставить ниже void filefinder() метод в вашем коде и вызовите его из вашего main функция или редактировать функции, как вы хотите использовать его.

поскольку файлы и подкаталоги каталога обычно хранятся в древовидной структуре, интуитивно понятным способом является использование алгоритма DFS для рекурсивного обхода каждого из них. Вот пример в операционной системе windows с помощью основных файловых функций в io.h. Вы можете заменить эти функции в другой платформе. Что я хочу выразить, так это то, что основная идея DFS идеально подходит для этой проблемы.

Я попытался следовать примеру, приведенному в и ответы и, возможно, стоит отметить, что это выглядит так, как будто std::filesystem::directory_entry было изменено, чтобы не было перегрузки << оператора. Вместо std::cout << p << std::endl; мне пришлось использовать следующее, чтобы скомпилировать и заставить его работать:

пыталась передать p на std::cout << вылилось в ошибку по перегрузке.

просто то, что я хочу поделиться и поблагодарить вас за чтение материала. Поиграйте с функцией немного, чтобы понять ее. Тебе может понравиться. e означало расширение, p-путь, а s-разделитель пути.

Если путь передается без конечного разделителя, разделитель будет добавлен к пути. Для расширения, если введена пустая строка, функция вернет любой файл, который не имеет расширения в своем имени. Если бы одна звезда была вводится, чем все файлы в каталоге будут возвращены. Если длина e больше 0, но не является единицей*, то точка будет добавлена к e, если e не содержит точку в нулевом положении.

для возвращаемого значения. Если возвращается карта нулевой длины, то ничего не найдено, но каталог был открыт нормально. Если индекс 999 доступен из возвращаемого значения, но размер карты равен только 1, это означает, что возникла проблема с открытием пути к каталогу.

обратите внимание, что для эффективности, эту функцию можно разделить в 3 более небольших функции. Кроме того, вы можете создать функцию вызывающего абонента, которая определит, какую функцию он будет вызывать на основе ввода. Почему это более эффективно? Сказал, что если вы собираетесь захватить все, что является файлом, делая этот метод, подфункция, построенная для захвата всех файлов, просто захватит все, что является файлами, и не нужно оценивать любые другие ненужные условия каждый раз, когда он нашел файл.

Это было бы также применяются, когда вы захватить файлы, которые не имеют расширения. Определенная встроенная функция для этой цели будет оценивать только погоду, если найденный объект является файлом, а затем, имеет ли имя файла точку в нем.

сохранение может быть не так много, если Вы читаете только каталоги с не так много файлов. Но если Вы читаете массовое количество каталогов или если каталог имеет пару сотен тысяч файлов, это может быть огромная экономия.

Как я могу определить список файлов в каталоге из моего кода C или C ++?

Мне не разрешено выполнять команду ls и анализировать результаты из моей программы.

ОБНОВЛЕНИЕ 2017 г. :

В C ++ 17 теперь есть официальный способ перечисления файлов вашей файловой системы: std::filesystem . Ниже приведен отличный ответ Shreevardhan с этим исходным кодом (этот код может вызывать ошибки):

Старый ответ:

В небольших и простых задачах не использую boost, я использую dirent.h . Он доступен как стандартный заголовок в UNIX, а также доступен для Windows через слой совместимости , созданный Тони Ронкко .

Это всего лишь небольшой файл заголовка, который выполняет большую часть необходимых вам простых вещей без использования большого подхода на основе шаблонов, такого как ускорение (без обид, мне нравится ускорение!).

В C ++ 17 теперь есть std::filesystem::directory_iterator , который можно использовать в виде

К сожалению, стандарт C ++ не определяет стандартный способ работы с файлами и папками таким образом.

Поскольку кроссплатформенного способа нет, лучший кроссплатформенный способ - использовать такую ​​библиотеку, как модуль файловой системы boost.

Кросс-платформенный метод повышения:

Следующая функция, учитывая путь к каталогу и имя файла, рекурсивно ищет в каталоге и его подкаталогах имя файла, возвращая логическое значение и, в случае успеха, путь к найденному файлу.

Источник со страницы повышения, упомянутой выше.

Для систем на базе Unix / Linux:

Пример кода, который ищет в каталоге запись `` имя '':

Исходный код из приведенных выше страниц руководства.

Для систем на базе Windows:

В следующем примере C ++ показано минимальное использование FindFirstFile.

Исходный код с вышеуказанных страниц msdn.

Достаточно одной функции, вам не нужно использовать сторонние библиотеки (для Windows).

PS: как упомянул @Sebastian, вы можете изменить *.* на *.ext , чтобы получить только EXT-файлы (т.е. определенного типа) в этом каталоге.

Для решения только на C, пожалуйста, проверьте это. Требуется только дополнительный заголовок:

Некоторые преимущества перед другими вариантами:

  • Это портативно - обертывает POSIX dirent и Windows FindFirstFile
  • Он использует readdir_r там, где это возможно, что означает (обычно) потокобезопасный
  • Поддерживает Windows UTF-16 с помощью тех же макросов UNICODE
  • Это C90, поэтому его могут использовать даже очень древние компиляторы.

Я рекомендую использовать glob с этой многоразовой оболочкой. Он генерирует vector<string> , соответствующий путям к файлам, которые соответствуют шаблону глобуса:

Что затем можно вызвать с помощью обычного системного шаблона подстановки, например:

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

Это используемая структура (присутствует в dirent.h ):

Вот очень простой код в C++11 , использующий библиотеку boost::filesystem для получения имен файлов в каталоге (исключая имена папок):

Почему бы не использовать glob() ?

Попробуйте boost для метода x-platform

Или просто используйте файлы, специфичные для вашей ОС.

Ознакомьтесь с этим классом, который использует win32 api. Просто создайте экземпляр, указав foldername , из которого вы хотите получить листинг, затем вызовите метод getNextFile , чтобы получить следующий filename из каталога. Думаю, ему нужны windows.h и stdio.h .

Руководство GNU FTW

Кроме того, иногда полезно сразу перейти к источнику (каламбур). Вы можете многому научиться, заглянув внутрь некоторых из наиболее распространенных команд в Linux. Я установил простое зеркало coreutils GNU на github (для чтения).

Возможно, это не относится к Windows, но с помощью этих методов можно иметь несколько случаев использования вариантов Unix.

Надеюсь, это поможет.

Ответ Шривардхана отлично работает. Но если вы хотите использовать его в C ++ 14, просто внесите изменения namespace fs = experimental::filesystem;

Надеюсь, этот код вам поможет.

Эта реализация реализует вашу цель, динамически заполняя массив строк содержимым указанного каталога.

Тогда просто прочтите файл.

РЕДАКТИРОВАТЬ: этот ответ следует рассматривать как взлом, но он действительно работает (хотя и для конкретной платформы), если у вас нет доступа к более элегантным решениям.

У меня это работает. Извините, если я не могу вспомнить источник. Вероятно, это со страницы руководства.

Вы можете напрямую получить все файлы в корневом каталоге, используя std :: experimental :: filesystem :: directory_iterator (). Затем прочтите названия этих файловых путей.

Этот ответ должен работать для пользователей Windows, у которых возникли проблемы с работой с Visual Studio с любым другим ответом.

Загрузите файл dirent.h со страницы github. Но лучше просто использовать файл Raw dirent.h и следовать моим инструкциям ниже (так я заставил его работать).

Перейдите в свой проект и добавьте новый элемент ( Ctrl + Shift + A ). Добавьте файл заголовка (.h) и назовите его dirent.h.

Вставьте код Raw dirent.h в свой заголовок.

Включите в свой код "dirent.h".

Поместите приведенный ниже метод void filefinder() в свой код и вызовите его из своей функции main или отредактируйте функцию, как вы хотите ее использовать.

Поскольку файлы и подкаталоги каталога обычно хранятся в древовидной структуре, интуитивно понятным способом является использование алгоритма DFS для рекурсивного обхода каждого из них. Вот пример в операционной системе Windows с использованием основных файловых функций в io.h. Вы можете заменить эти функции на другой платформе. Я хочу сказать, что основная идея DFS полностью решает эту проблему.

Я попытался последовать примеру, приведенному в обоих answers, и, возможно, стоит отметить, что похоже, что std::filesystem::directory_entry был изменен, чтобы не иметь перегрузки оператора << . Вместо std::cout << p << std::endl; мне пришлось использовать следующее, чтобы скомпилировать и заставить его работать:

Попытка передать p самостоятельно в std::cout << привела к отсутствующей ошибке перегрузки.

Это решение для Windows.

Поскольку я хотел передать std :: string и вернуть вектор строк, мне пришлось сделать пару преобразований.

Просто кое-что, чем я хочу поделиться и поблагодарить вас за материал для чтения. Поиграйте с функцией, чтобы понять ее. Вам это может понравиться. e означает расширение, p - путь, а s - разделитель пути.

Если путь передается без конечного разделителя, к пути будет добавлен разделитель. Для расширения, если введена пустая строка, функция вернет любой файл, в имени которого нет расширения. Если была введена одна звездочка, будут возвращены все файлы в каталоге. Если длина e больше 0, но не является одиночным *, то точка будет добавлена ​​к e, если e не содержал точки в нулевой позиции.

Для возвращаемого значения. Если возвращается карта нулевой длины, значит, ничего не было найдено, но каталог был открыт нормально. Если индекс 999 доступен из возвращаемого значения, но размер карты равен только 1, это означает, что возникла проблема с открытием пути к каталогу.

Обратите внимание, что для повышения эффективности эту функцию можно разделить на 3 более мелкие функции. Вдобавок к этому вы можете создать вызывающую функцию, которая будет определять, какую функцию он будет вызывать, на основе ввода. Почему это эффективнее? Сказано, что если вы собираетесь захватить все, что является файлом, выполняя этот метод, подфункция, созданная для захвата всех файлов, будет просто захватывать все, что является файлами, и не должна оценивать какие-либо другие ненужные условия каждый раз, когда она находит файл.

Это также относится к случаям, когда вы захватываете файлы без расширения. Специальная встроенная функция для этой цели будет оценивать погоду только в том случае, если найденный объект является файлом, а затем, есть ли в имени файла точка.

Экономия может быть небольшой, если вы читаете только каталоги с небольшим количеством файлов. Но если вы читаете большое количество каталогов или если в каталоге есть несколько сотен тысяч файлов, это может быть огромной экономией.

Перечислимые коллекции дают более высокую производительность, чем массивы, если вы работаете с большими коллекциями файлов и каталогов. Чтобы перечислить каталоги и файлы, вы можете применить методы, которые возвращают перечисляемую коллекцию имен каталогов или файлов, либо их объекты DirectoryInfo, FileInfo или FileSystemInfo.

Если вы хотите найти и вернуть только имена каталогов или файлов, используйте методы перечисления из класса Directory. Если вы хотите найти и вернуть другие свойства каталогов или файлов, используйте классы DirectoryInfo и FileSystemInfo.

Кроме того, можно использовать перечисляемые коллекции из этих методов в качестве параметра IEnumerable<T> для конструкторов классов коллекций, таких как List<T>.

В следующей таблице обобщаются методы, которые возвращают перечисляемые коллекции файлов и каталогов:

Что нужно найти и вернуть Используемый метод
Имена каталогов Directory.EnumerateDirectories
Сведения о каталогах (DirectoryInfo) DirectoryInfo.EnumerateDirectories
Имена файлов Directory.EnumerateFiles
Сведения о файлах (FileInfo) DirectoryInfo.EnumerateFiles
Имена записей файловой системы Directory.EnumerateFileSystemEntries
Сведения о записи файловой системы (FileSystemInfo) DirectoryInfo.EnumerateFileSystemInfos
Имена каталогов и файлов Directory.EnumerateFileSystemEntries

Несмотря на то, что у вас есть возможность немедленно перечислить все файлы во вложенных каталогах родительского каталога, применив параметр AllDirectories необязательного перечисления SearchOption, из-за ошибок UnauthorizedAccessException перечисление может оказаться неполным. Вы можете реализовать перехват таких исключений, сначала перечислив каталоги, а затем файлы.

Читайте также: