मैं सी या सी ++ का उपयोग करके निर्देशिका में फ़ाइलों की सूची कैसे प्राप्त कर सकता हूं?


592

मैं अपने C या C ++ कोड के अंदर से निर्देशिका में फ़ाइलों की सूची कैसे निर्धारित कर सकता हूं?

मुझे lsकमांड को निष्पादित करने और मेरे कार्यक्रम के परिणामों को पार्स करने की अनुमति नहीं है ।




1
@chrish - हाँ, लेकिन इस क्लासिक के पास "मुझे 'ls' निष्पादित करने की अनुमति नहीं है"! यह ठीक है कि मुझे कंप्यूटर विज्ञान का पहला वर्ष कैसा लगेगा। ; डी <3 x
जेम्स बेडफ़ोर्ड

1
C और C ++ समान भाषा नहीं हैं। इसलिए, इस कार्य को पूरा करने की प्रक्रिया दोनों भाषाओं में अलग-अलग होगी। कृपया एक को चुना और उसके अनुसार पुनः टैग करें।
एमडी एक्सएफ

2
और न तो उन भाषाओं में से (C ++ 17 के बाद से C ++ के अलावा) यहां तक ​​कि एक निर्देशिका की अवधारणा भी है - इसलिए किसी भी उत्तर की संभावना आपके ओएस पर निर्भर होने की संभावना है, या आपके द्वारा उपयोग किए जा रहे किसी भी अमूर्त पुस्तकालयों पर।
टॉबी स्पाइट

जवाबों:


809

छोटे और सरल कार्यों में मैं बूस्ट का उपयोग नहीं करता, मैं dirent.h का उपयोग करता हूं जो कि विंडोज़ के लिए भी उपलब्ध है:

DIR *dir;
struct dirent *ent;
if ((dir = opendir ("c:\\src\\")) != NULL) {
  /* print all the files and directories within directory */
  while ((ent = readdir (dir)) != NULL) {
    printf ("%s\n", ent->d_name);
  }
  closedir (dir);
} else {
  /* could not open directory */
  perror ("");
  return EXIT_FAILURE;
}

यह सिर्फ एक छोटी सी हैडर फ़ाइल है और इसे बढ़ावा देने (कोई अपराध नहीं, मुझे पसंद है!) जैसे बड़े टेम्पलेट-आधारित दृष्टिकोण का उपयोग किए बिना अधिकांश सरल सामान की आवश्यकता होती है।

विंडोज़ संगतता परत का लेखक टोनी रोंको है। यूनिक्स में, यह एक मानक हेडर है।

अद्यतन २०१ATE :

C ++ 17 में अब आपकी फाइल सिस्टम की फाइलों को सूचीबद्ध करने का एक आधिकारिक तरीका है std::filesystem:। इस स्रोत कोड के साथ नीचे श्रीवर्धन का एक उत्कृष्ट उत्तर है :

#include <string>
#include <iostream>
#include <filesystem>
namespace fs = std::filesystem;

int main()
{
    std::string path = "/path/to/directory";
    for (const auto & entry : fs::directory_iterator(path))
        std::cout << entry.path() << std::endl;
}

5
@ArtOfWarfare: जब इस सवाल का जवाब दिया गया तो टिनिडिर भी नहीं बना था। इसके अलावा यह dirent (POSIX) और FindFirstFile (Windows) के आसपास एक आवरण है, जबकि dirent.h सिर्फ windows के लिए dirent लपेटता है। मुझे लगता है कि यह एक व्यक्तिगत स्वाद है, लेकिन dirent.h एक मानक के रूप में अधिक महसूस करता है
पीटर पार्कर

7
@ जोश: क्योंकि * एनआर आंतरिक प्रतिनिधित्व का सिर्फ एक लौटा हुआ सूचक है। निर्देशिका को बंद करने से आप * पास को भी समाप्त कर देंगे। जैसा कि * ent केवल पढ़ने के लिए है, यह एक समझदार डिजाइन है, मुझे लगता है।
पीटर पार्कर

42
लोग असली हो जाओ !! यह 2009 का एक प्रश्न है और इसमें वी। एस। का उल्लेख भी नहीं किया गया है। इसलिए आलोचना न करें कि आपका पूर्ण स्वामित्व (हालांकि काफी अच्छा) आईडीई सदियों पुराने ओएस मानकों का समर्थन नहीं कर रहा है। इसके अलावा मेरे जवाब में यह कहा गया है कि यह विंडोज़ के लिए "उपलब्ध" है, अब से और किसी भी समय के लिए किसी भी आईडीई में "शामिल" नहीं है ... मुझे पूरा यकीन है कि आप इसे डाउनलोड कर सकते हैं और इसे किसी डायर और वॉयला में शामिल कर सकते हैं।
पीटर पार्कर

6
जवाब भ्रामक है। यह इसके साथ शुरू होना चाहिए: " ... मैं dirent.h का उपयोग करता हूं , जिसके लिए एक विंडोज ओपन-सोर्स संगतता परत भी मौजूद है "।
रस्टेक्स

10
C ++ 14 के std::experimental::filesystemसाथ है , C ++ 17 के साथ है std::filesystem। नीचे श्रीवर्धन का उत्तर देखें। तो 3 पार्टी पुस्तकालयों के लिए कोई ज़रूरत नहीं है।
रूई डंटन

346

C ++ 17 में अब एक है std::filesystem::directory_iterator, जिसका उपयोग किया जा सकता है

#include <string>
#include <iostream>
#include <filesystem>
namespace fs = std::filesystem;

int main() {
    std::string path = "/path/to/directory";
    for (const auto & entry : fs::directory_iterator(path))
        std::cout << entry.path() << std::endl;
}

इसके अलावा, std::filesystem::recursive_directory_iteratorउपनिर्देशिकाओं को भी पुनरावृत्त कर सकते हैं।


27
AFAIK का उपयोग C ++ 14 में भी किया जा सकता है, लेकिन वहां यह अभी भी प्रायोगिक है namespace fs = std::experimental::filesystem;:। हालांकि यह ठीक काम करने लगता है।
पीटरके ज़ूल

7
यह वर्तमान उपयोग के लिए पसंदीदा उत्तर होना चाहिए (C ++ 17 से शुरू)
हरी डायोड

4
गुजरने std::filesystem::pathके दौरान std::cout, उद्धरण चिह्नों को आउटपुट में शामिल किया जाता है। उससे बचने के लिए, .string()एक निहित रूपांतरण (यहां std::cout << p.string() << std::endl;) के बजाय एक स्पष्ट करने के लिए पथ पर जाएं । उदाहरण: coliru.stacked-crooked.com/view?id=a55ea60bbd36a8a3
Roi Danton

2
फ़ाइल नामों में NON-ASCII वर्णों के बारे में क्या? std::wstringउपयोग नहीं किया जाना चाहिए या पुनरावृत्त से क्या प्रकार है?
औरदेरो

2
मुझे यकीन नहीं है कि अगर मैं इसमें अकेला हूँ, लेकिन लिंक किए बिना -lstdc++fs, मैं एक मिल जाएगा SIGSEGV (Address boundary error)। मुझे कहीं भी दस्तावेज में यह नहीं मिला कि यह आवश्यक था, और लिंकर ने कोई सुराग नहीं दिया। यह g++ 8.3.0और दोनों के लिए काम किया clang 8.0.0-3। क्या किसी के पास कोई अंतर्दृष्टि है जहां इस तरह की चीजें डॉक्स / स्पेक्स में निर्दिष्ट हैं?
स्वैग

229

दुर्भाग्य से सी ++ मानक इस तरह से फ़ाइलों और फ़ोल्डरों के साथ काम करने के एक मानक तरीके को परिभाषित नहीं करता है।

चूंकि कोई क्रॉस प्लेटफ़ॉर्म तरीका नहीं है, इसलिए सबसे अच्छा क्रॉस प्लेटफ़ॉर्म तरीका लाइब्रेरी का उपयोग करना है जैसे कि बूस्ट फाइल सिस्टम मॉड्यूल

प्लेटफ़ॉर्म को बढ़ावा देने की विधि:

निम्नलिखित फ़ंक्शन, एक निर्देशिका पथ और एक फ़ाइल नाम दिया गया है, पुन: फ़ाइल निर्देशिका के लिए निर्देशिका और उसके उप-निर्देशिकाओं की खोज करता है, एक बूल वापस कर रहा है, और यदि सफल हो, तो उस फ़ाइल का पथ जो पाया गया था।

bool find_file(const path & dir_path,         // in this directory,
               const std::string & file_name, // search for this name,
               path & path_found)             // placing path here if found
{
    if (!exists(dir_path)) 
        return false;

    directory_iterator end_itr; // default construction yields past-the-end

    for (directory_iterator itr(dir_path); itr != end_itr; ++itr)
    {
        if (is_directory(itr->status()))
        {
            if (find_file(itr->path(), file_name, path_found)) 
                return true;
        }
        else if (itr->leaf() == file_name) // see below
        {
            path_found = itr->path();
            return true;
        }
    }
    return false;
}

ऊपर उल्लेखित बूस्ट पेज से स्रोत।

यूनिक्स / लिनक्स आधारित प्रणालियों के लिए:

आप opendir / readdir / shutir का उपयोग कर सकते हैं ।

नमूना कोड जो प्रविष्टि `` नाम 'के लिए एक निर्देशिका खोजता है:

len = strlen(name);
dirp = opendir(".");
while ((dp = readdir(dirp)) != NULL)
        if (dp->d_namlen == len && !strcmp(dp->d_name, name)) {
                (void)closedir(dirp);
                return FOUND;
        }
(void)closedir(dirp);
return NOT_FOUND;

उपरोक्त मैन पेज से सोर्स कोड।

विंडोज आधारित प्रणालियों के लिए:

आप Win32 एपीआई का उपयोग कर सकते हैं FindFirstFile / FindNextFile / FindClose कार्य करता है।

निम्न C ++ उदाहरण आपको FindFirstFile का न्यूनतम उपयोग दिखाता है।

#include <windows.h>
#include <tchar.h>
#include <stdio.h>

void _tmain(int argc, TCHAR *argv[])
{
   WIN32_FIND_DATA FindFileData;
   HANDLE hFind;

   if( argc != 2 )
   {
      _tprintf(TEXT("Usage: %s [target_file]\n"), argv[0]);
      return;
   }

   _tprintf (TEXT("Target file is %s\n"), argv[1]);
   hFind = FindFirstFile(argv[1], &FindFileData);
   if (hFind == INVALID_HANDLE_VALUE) 
   {
      printf ("FindFirstFile failed (%d)\n", GetLastError());
      return;
   } 
   else 
   {
      _tprintf (TEXT("The first file found is %s\n"), 
                FindFileData.cFileName);
      FindClose(hFind);
   }
}

उपरोक्त msdn पृष्ठों से स्रोत कोड।


उपयोग:FindFirstFile(TEXT("D:\\IMAGE\\MYDIRECTORY\\*"), &findFileData);
Константин Ван

7
C ++ 14 के std::experimental::filesystemसाथ, C ++ 17 के साथ है std::filesystem, जिसमें बूस्ट के समान कार्यक्षमता है (lib बूस्ट से ली गई हैं)। नीचे श्रीवर्धन का उत्तर देखें।
रूई डंटन

खिड़कियों के लिए, docs.microsoft.com/en-us/windows/desktop/FileIO/… देखें। विवरण के लिए
FindOutIslamNow

90

एक फ़ंक्शन पर्याप्त है, आपको किसी भी 3-पार्टी लाइब्रेरी (विंडोज के लिए) का उपयोग करने की आवश्यकता नहीं है।

#include <Windows.h>

vector<string> get_all_files_names_within_folder(string folder)
{
    vector<string> names;
    string search_path = folder + "/*.*";
    WIN32_FIND_DATA fd; 
    HANDLE hFind = ::FindFirstFile(search_path.c_str(), &fd); 
    if(hFind != INVALID_HANDLE_VALUE) { 
        do { 
            // read all (real) files in current folder
            // , delete '!' read other 2 default folder . and ..
            if(! (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) ) {
                names.push_back(fd.cFileName);
            }
        }while(::FindNextFile(hFind, &fd)); 
        ::FindClose(hFind); 
    } 
    return names;
}

पुनश्च: के रूप में @Sebastian ने उल्लेख किया है, तो आप को बदल सकता है *.*करने के लिए *.extआदेश केवल EXT-फ़ाइलें प्राप्त करने (एक विशेष प्रकार के अर्थात्) कि निर्देशिका में में।


20
यह समाधान यदि प्लेटफ़ॉर्म-विशिष्ट। यही कारण है कि आपको 3-पार्टी लाइब्रेरी की आवश्यकता है।
क्रैक्सर

9
@kraxor हां, यह केवल विंडोज में काम करता है, लेकिन ओपी कभी भी क्रॉस-प्लेटफॉर्म समाधान के लिए नहीं कहता है। BTW, मैं हमेशा 3-पुस्तकालयों (यदि संभव हो तो) का उपयोग किए बिना कुछ चुनना पसंद करता हूं।
हरोहुयंगताओ

7
@herohuyongtao ओपी ने कभी भी एक मंच निर्दिष्ट नहीं किया है, और एक सामान्य प्रश्न के लिए एक भारी मंच पर निर्भर समाधान देना भ्रामक हो सकता है। (क्या होगा अगर कोई एक-लाइन समाधान है जो केवल PlayStation 3 पर काम करता है? क्या यह एक अच्छा जवाब है?) मैं आपको आपके उत्तर को संपादित करने के लिए कहता हूं कि यह केवल Windows पर काम करता है, मुझे लगता है कि यह इस तरह से ठीक है।
क्रैक्सर

1
@herohuyongtao ओपी ने उल्लेख किया कि वह ls को पार्स नहीं कर सकता है, जिसका अर्थ है कि वह शायद यूनिक्स पर है .. वैसे भी, विंडोज के लिए अच्छा जवाब।
थॉमस

2
मैं एक का उपयोग कर समाप्त हो गया std::vector<std::wstring>और फिर fileName.c_str()तार का एक वेक्टर, जो संकलन नहीं होगा के बजाय।
पेरीसी

51

C केवल समाधान के लिए, कृपया इसे देखें। इसके लिए केवल एक अतिरिक्त शीर्ष लेख की आवश्यकता होती है:

https://github.com/cxong/tinydir

tinydir_dir dir;
tinydir_open(&dir, "/path/to/dir");

while (dir.has_next)
{
    tinydir_file file;
    tinydir_readfile(&dir, &file);

    printf("%s", file.name);
    if (file.is_dir)
    {
        printf("/");
    }
    printf("\n");

    tinydir_next(&dir);
}

tinydir_close(&dir);

अन्य विकल्पों पर कुछ फायदे:

  • यह पोर्टेबल है - POSIX dirent और Windows FindFirstFile को लपेटता है
  • यह readdir_rजहां उपलब्ध है, इसका उपयोग करता है, जिसका अर्थ है कि यह (आमतौर पर) थ्रेडसेफ़ है
  • एक ही UNICODEमैक्रोज़ के माध्यम से विंडोज UTF-16 का समर्थन करता है
  • यह C90 है इसलिए बहुत प्राचीन संकलक भी इसका उपयोग कर सकते हैं

2
बहुत अच्छा सुझाव है। मैं एक खिड़कियों कंप्यूटर पर परीक्षण नहीं किया अभी तक, लेकिन यह ओएस एक्स पर शानदार ढंग से काम करता है
ArtOfWarfare

पुस्तकालय std :: string का समर्थन नहीं करता है, इसलिए आप tinydir_open को file.c_str () पास नहीं कर सकते। यह इस मामले में msvc 2015 पर संकलन के दौरान त्रुटि C2664 को विविधता देता है।
Stepan याकोवेंको

33

मैं globइस पुन: प्रयोज्य आवरण के साथ उपयोग करने की सलाह देता हूं । यह vector<string>ग्लोब पैटर्न में फिट होने वाले फ़ाइल पथ के लिए संगत बनाता है :

#include <glob.h>
#include <vector>
using std::vector;

vector<string> globVector(const string& pattern){
    glob_t glob_result;
    glob(pattern.c_str(),GLOB_TILDE,NULL,&glob_result);
    vector<string> files;
    for(unsigned int i=0;i<glob_result.gl_pathc;++i){
        files.push_back(string(glob_result.gl_pathv[i]));
    }
    globfree(&glob_result);
    return files;
}

जिसे तब सामान्य सिस्टम वाइल्डकार्ड पैटर्न के साथ बुलाया जा सकता है जैसे:

vector<string> files = globVector("./*");

2
परीक्षण करें कि ग्लोब () शून्य है।
केमिली गौडेय्यून

जैसा कि आप की सिफारिश की मैं glob.h का उपयोग करना चाहूंगा। लेकिन फिर भी, मैं .h फ़ाइल को शामिल नहीं कर सकता: यह कहता है No such file or directory। क्या आप मुझे बता सकते हैं कि कृपया इस मुद्दे को कैसे हल करें?
टॉफुव

ध्यान दें कि यह दिनचर्या केवल एक स्तर गहरा (कोई पुनरावृत्ति नहीं) जाती है। यह यह निर्धारित करने के लिए एक त्वरित जांच भी नहीं करता है कि यह एक फ़ाइल या निर्देशिका है, जिसे आप आसानी से स्विच GLOB_TILDEकरके GLOB_TILDE | GLOB_MARKऔर फिर स्लैश में समाप्त होने वाले रास्तों के लिए जाँच कर सकते हैं । जरूरत पड़ने पर आपको इसमें संशोधन करना पड़ेगा।
Volomike

क्या यह क्रॉस-प्लेटफॉर्म संगत है?
निखिल ऑगस्टीन

दुर्भाग्य से आप समान रूप से छिपी हुई फ़ाइलों को नहीं ढूंढ सकते हैं glob
LmTinyToon 11

23

निर्देशिका में फ़ाइल नाम प्राप्त करने के लिए लाइब्रेरी का C++11उपयोग boost::filesystemकरने में एक बहुत ही सरल कोड है (फ़ोल्डर नामों को छोड़कर):

#include <string>
#include <iostream>
#include <boost/filesystem.hpp>
using namespace std;
using namespace boost::filesystem;

int main()
{
    path p("D:/AnyFolder");
    for (auto i = directory_iterator(p); i != directory_iterator(); i++)
    {
        if (!is_directory(i->path())) //we eliminate directories
        {
            cout << i->path().filename().string() << endl;
        }
        else
            continue;
    }
}

आउटपुट की तरह है:

file1.txt
file2.dat

हाय, और मुझे यह पुस्तकालय कहां मिल सकता है?
अलेक्जेंडर लियोन VI

2
@Alexander De Leon: आप अपनी साइट पर इस पुस्तकालय प्राप्त कर सकते हैं boost.org , आरंभ करने की मार्गदर्शिका पहले, तो उनके उपयोग करें पढ़ने के boost::filesystemपुस्तकालय boost.org/doc/libs/1_58_0/libs/filesystem/doc/index.htm
बुरा

23

उपयोग क्यों नहीं glob()?

#include <glob.h>

glob_t glob_result;
glob("/your_directory/*",GLOB_TILDE,NULL,&glob_result);
for(unsigned int i=0; i<glob_result.gl_pathc; ++i){
  cout << glob_result.gl_pathv[i] << endl;
}

यह एक बेहतर उत्तर हो सकता है यदि आप आवश्यक शामिल की व्याख्या करते हैं।
वोलोमाइक

2
परीक्षण करें कि ग्लोब () शून्य देता है!
orbitcowboy

यह अच्छा है जब आप फ़ाइल आप इस तरह * .txt के रूप में देख रहे पता
बिश्केक झोउ

20

मुझे लगता है, नीचे स्निपेट का उपयोग सभी फाइलों को सूचीबद्ध करने के लिए किया जा सकता है।

#include <stdio.h>
#include <dirent.h>
#include <sys/types.h>

static void list_dir(const char *path)
{
    struct dirent *entry;
    DIR *dir = opendir(path);
    if (dir == NULL) {
        return;
    }

    while ((entry = readdir(dir)) != NULL) {
        printf("%s\n",entry->d_name);
    }

    closedir(dir);
}

निम्नलिखित संरचना की संरचना है

struct dirent {
    ino_t d_ino; /* inode number */
    off_t d_off; /* offset to the next dirent */
    unsigned short d_reclen; /* length of this record */
    unsigned char d_type; /* type of file */
    char d_name[256]; /* filename */
};

मुझे यह पसंद है।
आत्मबूट

10

एक्स-प्लेटफ़ॉर्म विधि के लिए बढ़ावा देने का प्रयास करें

http://www.boost.org/doc/libs/1_38_0/libs/filesystem/doc/index.htm

या बस अपने OS विशिष्ट फ़ाइल सामग्री का उपयोग करें।


हालांकि यह लिंक प्रश्न का उत्तर दे सकता है, लेकिन उत्तर के आवश्यक भागों को शामिल करना और संदर्भ के लिए लिंक प्रदान करना बेहतर है। लिंक-केवल उत्तर अमान्य हो सकते हैं यदि लिंक किए गए पृष्ठ बदल जाते हैं। - समीक्षा से
ice1000

@ ice1000 गंभीरता से? यह क्यू एंड ए 2009 से है
टिम

8

इस वर्ग को देखें जो win32 एपीआई का उपयोग करता है। बस एक उदाहरण प्रदान करें foldernameजिससे आप लिस्टिंग चाहते हैं फिर निर्देशिका से getNextFileअगली प्राप्त करने के लिए विधि को कॉल करें filename। मैं इसे की आवश्यकता है windows.hऔर stdio.h

class FileGetter{
    WIN32_FIND_DATAA found; 
    HANDLE hfind;
    char folderstar[255];       
    int chk;

public:
    FileGetter(char* folder){       
        sprintf(folderstar,"%s\\*.*",folder);
        hfind = FindFirstFileA(folderstar,&found);
        //skip .
        FindNextFileA(hfind,&found);        
    }

    int getNextFile(char* fname){
        //skips .. when called for the first time
        chk=FindNextFileA(hfind,&found);
        if (chk)
            strcpy(fname, found.cFileName);     
        return chk;
    }

};

6

जीएनयू मैनुअल एफटीडब्ल्यू

http://www.gnu.org/software/libc/manual/html_node/Simple-Directory-Lister.html#Simple-Directory-Lister

इसके अलावा, कभी-कभी स्रोत पर सही जाना अच्छा होता है (इच्छित उद्देश्य)। आप लिनक्स में कुछ सबसे सामान्य कमांड्स के इंसर्ड को देखकर बहुत कुछ सीख सकते हैं। मैंने गितुब (पढ़ने के लिए) पर जीएनयू के कोर्यूटिल्स का एक सरल दर्पण स्थापित किया है।

https://github.com/homer6/gnu_coreutils/blob/master/src/ls.c

शायद यह विंडोज को संबोधित नहीं करता है, लेकिन इन तरीकों का उपयोग करके यूनिक्स वेरिएंट का उपयोग करने के कई मामले हो सकते हैं।

उम्मीद है की वो मदद करदे...


5

श्रीवर्धन का उत्तर महान काम करता है। लेकिन अगर आप इसे c ++ 14 में उपयोग करना चाहते हैं तो बस एक बदलाव करेंnamespace fs = experimental::filesystem;

अर्थात,

#include <string>
#include <iostream>
#include <filesystem>

using namespace std;
namespace fs = experimental::filesystem;

int main()
{
    string path = "C:\\splits\\";
    for (auto & p : fs::directory_iterator(path))
        cout << p << endl;
    int n;
    cin >> n;
}

4
char **getKeys(char *data_dir, char* tablename, int *num_keys)
{
    char** arr = malloc(MAX_RECORDS_PER_TABLE*sizeof(char*));
int i = 0;
for (;i < MAX_RECORDS_PER_TABLE; i++)
    arr[i] = malloc( (MAX_KEY_LEN+1) * sizeof(char) );  


char *buf = (char *)malloc( (MAX_KEY_LEN+1)*sizeof(char) );
snprintf(buf, MAX_KEY_LEN+1, "%s/%s", data_dir, tablename);

DIR* tableDir = opendir(buf);
struct dirent* getInfo;

readdir(tableDir); // ignore '.'
readdir(tableDir); // ignore '..'

i = 0;
while(1)
{


    getInfo = readdir(tableDir);
    if (getInfo == 0)
        break;
    strcpy(arr[i++], getInfo->d_name);
}
*(num_keys) = i;
return arr;
}

3

मुझे उम्मीद है कि यह कोड आपकी मदद करेगा।

#include <windows.h>
#include <iostream>
#include <string>
#include <vector>
using namespace std;

string wchar_t2string(const wchar_t *wchar)
{
    string str = "";
    int index = 0;
    while(wchar[index] != 0)
    {
        str += (char)wchar[index];
        ++index;
    }
    return str;
}

wchar_t *string2wchar_t(const string &str)
{
    wchar_t wchar[260];
    int index = 0;
    while(index < str.size())
    {
        wchar[index] = (wchar_t)str[index];
        ++index;
    }
    wchar[index] = 0;
    return wchar;
}

vector<string> listFilesInDirectory(string directoryName)
{
    WIN32_FIND_DATA FindFileData;
    wchar_t * FileName = string2wchar_t(directoryName);
    HANDLE hFind = FindFirstFile(FileName, &FindFileData);

    vector<string> listFileNames;
    listFileNames.push_back(wchar_t2string(FindFileData.cFileName));

    while (FindNextFile(hFind, &FindFileData))
        listFileNames.push_back(wchar_t2string(FindFileData.cFileName));

    return listFileNames;
}

void main()
{
    vector<string> listFiles;
    listFiles = listFilesInDirectory("C:\\*.txt");
    for each (string str in listFiles)
        cout << str << endl;
}

4
-1। string2wchar_tस्थानीय चर का पता देता है। इसके अलावा, आपको शायद अपने खुद के लिखने के बजाय WinAPI में उपलब्ध रूपांतरण विधियों का उपयोग करना चाहिए।
डैनियल कामिल कोजार

3

यह कार्यान्वयन आपके उद्देश्य को महसूस करता है, गतिशील रूप से निर्दिष्ट निर्देशिका की सामग्री के साथ तार की एक सरणी को भरता है।

int exploreDirectory(const char *dirpath, char ***list, int *numItems) {
    struct dirent **direntList;
    int i;
    errno = 0;

    if ((*numItems = scandir(dirpath, &direntList, NULL, alphasort)) == -1)
        return errno;

    if (!((*list) = malloc(sizeof(char *) * (*numItems)))) {
        fprintf(stderr, "Error in list allocation for file list: dirpath=%s.\n", dirpath);
        exit(EXIT_FAILURE);
    }

    for (i = 0; i < *numItems; i++) {
        (*list)[i] = stringDuplication(direntList[i]->d_name);
    }

    for (i = 0; i < *numItems; i++) {
        free(direntList[i]);
    }

    free(direntList);

    return 0;
}

मैं इसे कैसे कहूंगा? जब मैं इस फ़ंक्शन को पहले ifब्लॉक पर चलाने का प्रयास करता हूं, तो मुझे segfaults मिल रहा है । मैं इसके साथ बुला रहा हूँchar **list; int numItems; exploreDirectory("/folder",list, numItems);
हेल ​​टी

2

यह मेरे लिए काम करता है। मुझे खेद है कि अगर मुझे स्रोत याद नहीं है। यह शायद एक आदमी पृष्ठ से है।

#include <ftw.h>

int AnalizeDirectoryElement (const char *fpath, 
                            const struct stat *sb,
                            int tflag, 
                            struct FTW *ftwbuf) {

  if (tflag == FTW_F) {
    std::string strFileName(fpath);

    DoSomethingWith(strFileName);
  }
  return 0; 
}

void WalkDirectoryTree (const char * pchFileName) {

  int nFlags = 0;

  if (nftw(pchFileName, AnalizeDirectoryElement, 20, nFlags) == -1) {
    perror("nftw");
  }
}

int main() {
  WalkDirectoryTree("some_dir/");
}

2

आप std :: प्रयोगात्मक :: filesystem :: directory_iterator () का उपयोग करके अपनी रूट निर्देशिका में फ़ाइलों के सभी प्रत्यक्ष प्राप्त कर सकते हैं। फिर, इन पाथफाइल्स का नाम पढ़ें।

#include <iostream>
#include <filesystem>
#include <string>
#include <direct.h>
using namespace std;
namespace fs = std::experimental::filesystem;
void ShowListFile(string path)
{
for(auto &p: fs::directory_iterator(path))  /*get directory */
     cout<<p.path().filename()<<endl;   // get file name
}

int main() {

ShowListFile("C:/Users/dell/Pictures/Camera Roll/");
getchar();
return 0;
}

2

इस उत्तर को उन विंडोज उपयोगकर्ताओं के लिए काम करना चाहिए जिन्हें किसी अन्य उत्तर के साथ विजुअल स्टूडियो के साथ काम करने में परेशानी हुई है।

  1. Github पृष्ठ से dirent.h फ़ाइल डाउनलोड करें। लेकिन सिर्फ कच्चे dirent.h फ़ाइल का उपयोग करना बेहतर है और नीचे मेरे चरणों का पालन करें (यह है कि मुझे यह कैसे काम करना है)।

    Windows के लिए dirent.h के लिए Github पृष्ठ : dirent.h के लिए Github पृष्ठ

    कच्ची डिरेंट फ़ाइल: Raw dirent.h फ़ाइल

  2. अपने प्रोजेक्ट पर जाएं और एक नया आइटम ( Ctrl+ Shift+ A) जोड़ें। एक हेडर फ़ाइल (.h) जोड़ें और इसे dirent.h नाम दें।

  3. अपने हेडर में Raw dirent.h फ़ाइल कोड पेस्ट करें ।

  4. अपने कोड में "dirent.h" शामिल करें।

  5. नीचे दी गई void filefinder()विधि को अपने कोड में रखें और इसे अपने mainफ़ंक्शन से कॉल करें या फ़ंक्शन को संपादित करें कि आप इसका उपयोग कैसे करना चाहते हैं।

    #include <stdio.h>
    #include <string.h>
    #include "dirent.h"
    
    string path = "C:/folder"; //Put a valid path here for folder
    
    void filefinder()
    {
        DIR *directory = opendir(path.c_str());
        struct dirent *direntStruct;
    
        if (directory != NULL) {
            while (direntStruct = readdir(directory)) {
                printf("File Name: %s\n", direntStruct->d_name); //If you are using <stdio.h>
                //std::cout << direntStruct->d_name << std::endl; //If you are using <iostream>
            }
        }
        closedir(directory);
    }

1

सिस्टम इसे कहते हैं!

system( "dir /b /s /a-d * > file_names.txt" );

फिर बस फ़ाइल पढ़ें।

संपादित करें: इस जवाब को हैक माना जाना चाहिए, लेकिन यह वास्तव में काम करता है (यद्यपि एक मंच विशिष्ट तरीके से) यदि आपके पास अधिक सुरुचिपूर्ण समाधान तक पहुंच नहीं है।


7
मुझे 'ls' कमांड निष्पादित करने और मेरे कार्यक्रम के परिणामों को पार्स करने की अनुमति नहीं है। मुझे पता था कि कोई ऐसा व्यक्ति होगा जो इस तरह से कुछ भेजेगा ...
yyny

1

चूंकि फ़ाइलों और निर्देशिकाओं की उप-निर्देशिकाओं को आम तौर पर एक पेड़ की संरचना में संग्रहीत किया जाता है, इसलिए एक सहज तरीका डीएफएस एल्गोरिथ्म का उपयोग करके उनमें से प्रत्येक को पुनरावृत्ति करना है। यहाँ io.h में बुनियादी फ़ाइल फ़ंक्शंस का उपयोग करके विंडोज़ ऑपरेटिंग सिस्टम में एक उदाहरण है। आप इन कार्यों को अन्य प्लेटफ़ॉर्म में बदल सकते हैं। मैं यह व्यक्त करना चाहता हूं कि डीएफएस का मूल विचार इस समस्या से पूरी तरह से मिलता है।

#include<io.h>
#include<iostream.h>
#include<string>
using namespace std;

void TraverseFilesUsingDFS(const string& folder_path){
   _finddata_t file_info;
   string any_file_pattern = folder_path + "\\*";
   intptr_t handle = _findfirst(any_file_pattern.c_str(),&file_info);
   //If folder_path exsist, using any_file_pattern will find at least two files "." and "..", 
   //of which "." means current dir and ".." means parent dir
   if (handle == -1){
       cerr << "folder path not exist: " << folder_path << endl;
       exit(-1);
   }
   //iteratively check each file or sub_directory in current folder
   do{
       string file_name=file_info.name; //from char array to string
       //check whtether it is a sub direcotry or a file
       if (file_info.attrib & _A_SUBDIR){
            if (file_name != "." && file_name != ".."){
               string sub_folder_path = folder_path + "\\" + file_name;                
               TraverseFilesUsingDFS(sub_folder_path);
               cout << "a sub_folder path: " << sub_folder_path << endl;
            }
       }
       else
            cout << "file name: " << file_name << endl;
    } while (_findnext(handle, &file_info) == 0);
    //
    _findclose(handle);
}

1

मैंने दोनों उत्तरों में दिए गए उदाहरण का अनुसरण करने की कोशिश की और यह ध्यान देने योग्य हो सकता है कि ऐसा प्रतीत होता है जैसे कि ऑपरेटर के std::filesystem::directory_entryअधिभार को नहीं बदला गया है <<। इसके बजाय std::cout << p << std::endl;मुझे निम्नलिखित का उपयोग करने के लिए संकलित करने और इसे प्राप्त करने में सक्षम होना था:

#include <iostream>
#include <filesystem>
#include <string>
namespace fs = std::filesystem;

int main() {
    std::string path = "/path/to/directory";
    for(const auto& p : fs::directory_iterator(path))
        std::cout << p.path() << std::endl;
}

एक अतिभारित त्रुटि के परिणामस्वरूप pअपने आप से गुजरने की कोशिश कर रहा है std::cout <<


1

Herohuyongtao पोस्ट और कुछ अन्य पदों पर निर्माण:

http://www.cplusplus.com/forum/general/39766/

FindFirstFile का अपेक्षित इनपुट प्रकार क्या है?

स्ट्रिंग में wstring कैसे कन्वर्ट करें?

यह एक विंडोज समाधान है।

चूँकि मैं std :: string में पास होना चाहता था और स्ट्रिंग्स के एक वेक्टर को वापस करने के लिए मुझे कुछ रूपांतरण करना था।

#include <string>
#include <Windows.h>
#include <vector>
#include <locale>
#include <codecvt>

std::vector<std::string> listFilesInDir(std::string path)
{
    std::vector<std::string> names;
    //Convert string to wstring
    std::wstring search_path = std::wstring_convert<std::codecvt_utf8<wchar_t>>().from_bytes(path);
    WIN32_FIND_DATA fd;
    HANDLE hFind = FindFirstFile(search_path.c_str(), &fd);
    if (hFind != INVALID_HANDLE_VALUE) 
    {
        do 
        {
            // read all (real) files in current folder
            // , delete '!' read other 2 default folder . and ..
            if (!(fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) 
            {
                //convert from wide char to narrow char array
                char ch[260];
                char DefChar = ' ';
                WideCharToMultiByte(CP_ACP, 0, fd.cFileName, -1, ch, 260, &DefChar, NULL);
                names.push_back(ch);
            }
        } 
        while (::FindNextFile(hFind, &fd));
        ::FindClose(hFind);
    }
    return names;
}

यदि आप जानते हैं कि आप केवल मल्टीबाइट का उपयोग कर रहे हैं जो आप उपयोग कर सकते हैं WIN32_FIND_DATAA, FindFirstFileAऔर FindNextFileA। फिर यूनीकोड ​​में मल्टीबाइट या इनपुट में परिणाम बदलने की आवश्यकता नहीं होगी।
किरण थिलक

0

बस कुछ है जो मैं आपको पढ़ना सामग्री के लिए साझा करना और धन्यवाद करना चाहता हूं। इसे समझने के लिए फ़ंक्शन के साथ चारों ओर खेलें। आप इसे पसंद कर सकते हैं। ई विस्तार के लिए खड़ा था, पी पथ के लिए है, और एस पथ विभाजक के लिए है।

यदि विभाजक को समाप्त किए बिना पथ पारित किया जाता है, तो एक विभाजक को पथ में जोड़ा जाएगा। एक्सटेंशन के लिए, यदि खाली स्ट्रिंग इनपुट की जाती है, तो फ़ंक्शन किसी भी फ़ाइल को वापस कर देगा जिसमें उसके नाम पर एक्सटेंशन नहीं है। यदि निर्देशिका में सभी फ़ाइलों की तुलना में एकल सितारा इनपुट किया गया था, तो उसे वापस कर दिया जाएगा। यदि ई की लंबाई 0 से अधिक है, लेकिन एक * नहीं है, तो एक ई को ई से प्रीपे किया जाएगा यदि ई में शून्य स्थिति पर डॉट नहीं था।

वापसी मूल्य के लिए। यदि शून्य-लंबाई का नक्शा वापस किया जाता है, तो कुछ भी नहीं मिला, लेकिन निर्देशिका ठीक थी। यदि इंडेक्स 999 रिटर्न मान से उपलब्ध है, लेकिन मैप का आकार केवल 1 है, तो इसका मतलब है कि निर्देशिका पथ को खोलने में कोई समस्या थी।

ध्यान दें कि दक्षता के लिए, इस फ़ंक्शन को 3 छोटे कार्यों में विभाजित किया जा सकता है। उसके शीर्ष पर, आप एक कॉलर फ़ंक्शन बना सकते हैं जो यह पता लगाएगा कि इनपुट के आधार पर यह किस फ़ंक्शन को कॉल करने वाला है। वह अधिक कुशल क्यों है? कहा अगर आप सब कुछ फाइल करने जा रहे हैं, तो उस विधि को करने से सब फाइल को हथियाने के लिए बनाया गया सबफंक्शन बस वह सब हड़प जाएगा जो कि फाइलें हैं और किसी भी अन्य अनावश्यक स्थिति का मूल्यांकन करने की जरूरत नहीं है क्योंकि यह एक फाइल है।

यह तब भी लागू होता है जब आप उन फ़ाइलों को हड़प लेते हैं जिनमें एक्सटेंशन नहीं होता है। उस उद्देश्य के लिए एक विशिष्ट निर्मित फ़ंक्शन केवल मौसम के लिए मूल्यांकन करेगा यदि पाया गया ऑब्जेक्ट एक फ़ाइल है और फिर फ़ाइल के नाम में डॉट है या नहीं।

यदि आप केवल इतनी फ़ाइलों के साथ निर्देशिका नहीं पढ़ते हैं तो बचत बहुत अधिक नहीं हो सकती है। लेकिन अगर आप निर्देशिका की एक बड़ी राशि पढ़ रहे हैं या यदि निर्देशिका में कई सौ फाइलें हैं, तो यह एक बड़ी बचत हो सकती है।

#include <stdio.h>
#include <sys/stat.h>
#include <iostream>
#include <dirent.h>
#include <map>

std::map<int, std::string> getFile(std::string p, std::string e = "", unsigned char s = '/'){
    if ( p.size() > 0 ){
        if (p.back() != s) p += s;
    }
    if ( e.size() > 0 ){
        if ( e.at(0) != '.' && !(e.size() == 1 && e.at(0) == '*') ) e = "." + e;
    }

    DIR *dir;
    struct dirent *ent;
    struct stat sb;
    std::map<int, std::string> r = {{999, "FAILED"}};
    std::string temp;
    int f = 0;
    bool fd;

    if ( (dir = opendir(p.c_str())) != NULL ){
        r.erase (999);
        while ((ent = readdir (dir)) != NULL){
            temp = ent->d_name;
            fd = temp.find(".") != std::string::npos? true : false;
            temp = p + temp;

            if (stat(temp.c_str(), &sb) == 0 && S_ISREG(sb.st_mode)){
                if ( e.size() == 1 && e.at(0) == '*' ){
                    r[f] = temp;
                    f++;
                } else {
                    if (e.size() == 0){
                        if ( fd == false ){
                            r[f] = temp;
                            f++;
                        }
                        continue;
                    }

                    if (e.size() > temp.size()) continue;

                    if ( temp.substr(temp.size() - e.size()) == e ){
                        r[f] = temp;
                        f++;
                    }
                }
            }
        }

        closedir(dir);
        return r;
    } else {
        return r;
    }
}

void printMap(auto &m){
    for (const auto &p : m) {
        std::cout << "m[" << p.first << "] = " << p.second << std::endl;
    }
}

int main(){
    std::map<int, std::string> k = getFile("./", "");
    printMap(k);
    return 0;
}

0
#include<iostream>
#include <dirent.h>
using namespace std;
char ROOT[]={'.'};

void listfiles(char* path){
    DIR * dirp = opendir(path);
    dirent * dp;
    while ( (dp = readdir(dirp)) !=NULL ) {
         cout << dp->d_name << " size " << dp->d_reclen<<std::endl;
    }
    (void)closedir(dirp);
}

int main(int argc, char **argv)
{
    char* path;
    if (argc>1) path=argv[1]; else path=ROOT;

    cout<<"list files in ["<<path<<"]"<<std::endl;
    listfiles(path);

    return 0;
}

-1

इसने मेरे लिए काम किया। यह सभी फाइलों के नाम (कोई रास्ता नहीं) के साथ एक फाइल लिखता है। फिर यह उस txt फ़ाइल को पढ़ता है और आपके लिए प्रिंट करता है।

void DisplayFolderContent()
    {

        system("dir /n /b * > file_names.txt");
        char ch;
        std::fstream myStream("file_names.txt", std::fstream::in);
        while (myStream.get(ch))
        {
            std::cout << ch;
        }

    }
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.