@chrish - Sim, mas este aqui tem o clássico "Não tenho permissão para executar o 'ls'"! É exatamente como eu me sentiria no primeiro ano de Ciência da Computação. ; D <3 x
James Bedford
1
C e C ++ não são a mesma linguagem. Portanto, o procedimento para realizar esta tarefa será diferente nos dois idiomas. Por favor, escolha um e re-etiquete de acordo.
MD XF
2
E nenhuma dessas linguagens (exceto C ++ desde C ++ 17) tem o conceito de diretório - portanto, qualquer resposta provavelmente depende do seu sistema operacional ou de qualquer biblioteca de abstração que você possa estar usando.
precisa
Respostas:
809
Em tarefas pequenas e simples, não uso o boost, uso o dirent.h, que também está disponível para o Windows:
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;}
É apenas um pequeno arquivo de cabeçalho e faz a maioria das coisas simples que você precisa, sem usar uma grande abordagem baseada em modelo como impulso (sem ofensa, eu gosto de aumento!).
O autor da camada de compatibilidade do Windows é Toni Ronkko. No Unix, é um cabeçalho padrão.
ATUALIZAÇÃO 2017 :
Em C ++ 17 há agora uma maneira oficial de arquivos de lista de seu sistema de arquivos: std::filesystem. Há uma excelente resposta de Shreevardhan abaixo com este código-fonte:
@ArtOfWarfare: tinydir nem sequer foi criado quando esta pergunta foi respondida. Também é um invólucro em torno do dirent (POSIX) e FindFirstFile (Windows), enquanto o dirent.h apenas agrupa o dirent para janelas. Eu acho que é um gosto pessoal, mas dirent.h se sente mais como um padrão
Peter Parker
7
@ JoshC: porque * ent é apenas um ponteiro retornado da representação interna. fechando o diretório, você também eliminará o * ent. Como o * ent é apenas para leitura, acho que é um design sensato.
Peter Parker
42
as pessoas ficam reais !! Esta é uma pergunta de 2009 e nem sequer mencionou o VS. Portanto, não critique que seu IDE proprietário completo (embora bastante agradável) não esteja suportando padrões de sistema operacional com séculos de idade. Além disso, minha resposta disse que está "disponível" para o Windows, não "incluído" em qualquer IDE a partir de agora e para sempre ... Tenho certeza de que você pode baixar o dirent e colocá-lo em alguns incluem dir dir e pronto.
Peter Parker
6
A resposta é enganosa. Deve começar com: " ... eu uso o dirent.h , para o qual também existe uma camada de compatibilidade de código aberto do Windows ".
Rustyx
10
Com C ++ 14 existe std::experimental::filesystem, com C ++ 17 existe std::filesystem. Veja a resposta de Shreevardhan abaixo. Portanto, não há necessidade de bibliotecas de terceiros.
AFAIK também pode ser usado em C ++ 14, mas não é ainda experimental: namespace fs = std::experimental::filesystem;. Parece funcionar bem embora.
PeterK
7
Esta deve ser a resposta preferida para uso corrente (começando com C ++ 17)
diod verde
4
Preste atenção ao passar std::filesystem::pathpara std::cout, as aspas estão incluídas na saída. Para evitar isso, anexe .string()ao caminho para fazer uma conversão explícita em vez de implícita (aqui std::cout << p.string() << std::endl;). Exemplo: coliru.stacked-crooked.com/view?id=a55ea60bbd36a8a3
Roi Danton
2
E os caracteres NÃO ASCII nos nomes de arquivo? Não deve std::wstringser usado ou qual é o tipo do iterador?
anddero
2
Não tenho certeza se estou sozinho nisso, mas sem vincular a -lstdc++fs, eu obteria um SIGSEGV (Address boundary error). Não consegui encontrar em nenhum lugar da documentação que isso fosse necessário e o vinculador também não deu nenhuma pista. Isso funcionou para ambos g++ 8.3.0e clang 8.0.0-3. Alguém tem alguma idéia de onde essas coisas são especificadas nos documentos / especificações?
swalog 02/07/19
229
Infelizmente, o padrão C ++ não define uma maneira padrão de trabalhar com arquivos e pastas dessa maneira.
Como não existe uma maneira multiplataforma, a melhor maneira multiplataforma é usar uma biblioteca como o módulo de sistema de arquivos boost .
Método de aumento de plataforma cruzada:
A função a seguir, dado um caminho de diretório e um nome de arquivo, procura recursivamente o diretório e seus subdiretórios pelo nome do arquivo, retornando um booleano e, se bem-sucedido, o caminho para o arquivo encontrado.
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))returnfalse;
directory_iterator end_itr;// default construction yields past-the-endfor(directory_iterator itr(dir_path); itr != end_itr;++itr){if(is_directory(itr->status())){if(find_file(itr->path(), file_name, path_found))returntrue;}elseif(itr->leaf()== file_name)// see below{
path_found = itr->path();returntrue;}}returnfalse;}
Com o C ++ 14, existe std::experimental::filesystem, com o C ++ 17 std::filesystem, que possuem funcionalidades semelhantes às do boost (as bibliotecas são derivadas do boost). Veja a resposta de Shreevardhan abaixo.
Esta solução é específica da plataforma. Esse é o motivo pelo qual você precisa de bibliotecas de terceiros.
Kraxor
9
@kraxor Sim, ele só funciona no Windows, mas o OP nunca pede para ter uma solução de plataforma cruzada. BTW, eu sempre prefiro escolher algo sem usar a 3ª biblioteca (se possível).
Herohuyongtao 29/05
7
O @herohuyongtao OP nunca especificou uma plataforma, e fornecer uma solução altamente dependente da plataforma para uma pergunta genérica pode ser enganosa. (E se houver uma solução em uma linha que funcione apenas no PlayStation 3? Essa é uma boa resposta aqui?). Vejo que você editou sua resposta para afirmar que ela só funciona no Windows, acho que é bom assim.
Kraxor
1
@herohuyongtao OP mencionou que não pode analisar ls, o que significa que ele provavelmente está no unix .. de qualquer maneira, boa resposta para o Windows.
Thomas
2
Acabei usando std::vector<std::wstring>ae, em fileName.c_str()vez de um vetor de strings, que não seria compilado.
PerryC
51
Para uma solução apenas C, verifique isso. Requer apenas um cabeçalho extra:
Sugestão muito boa. Eu não testei-o em um computador com Windows ainda, mas funciona brilhantemente no OS X.
ArtOfWarfare
A biblioteca não suporta std :: string, portanto você não pode passar file.c_str () para tinydir_open. Emite o erro C2664 durante a compilação no msvc 2015 neste caso.
Stepan Yakovenko
33
Eu recomendo usar globcom este invólucro reutilizável. Ele gera um vector<string>caminho correspondente ao arquivo que se ajusta ao padrão glob:
Eu gostaria de usar glob.h como você recomendou. Ainda assim, não posso incluir o arquivo .h: está escrito No such file or directory. Você pode me dizer como resolver esse problema, por favor?
23616 Tofuw
Observe que essa rotina atinge apenas um nível de profundidade (sem recursão). Ele também não fazer uma verificação rápida para determinar se se trata de um arquivo ou pasta, o que você pode fazer facilmente, alternando GLOB_TILDEcom GLOB_TILDE | GLOB_MARKe, em seguida, verificar se há caminhos que terminam em uma barra. Você precisará fazer uma modificação, se precisar.
Volomike 15/05
Esta plataforma é compatível?
Nikhil Augustine
Infelizmente você não pode encontrar arquivos ocultos uniformemente via glob.
LmTinyToon 5/10
23
Aqui está um código muito simples no C++11uso da boost::filesystembiblioteca para obter nomes de arquivos em um diretório (excluindo nomes de pastas):
#include<string>#include<iostream>#include<boost/filesystem.hpp>usingnamespace std;usingnamespace 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;}elsecontinue;}}
struct dirent {ino_t d_ino;/* inode number */off_t d_off;/* offset to the next dirent */unsignedshort d_reclen;/* length of this record */unsignedchar d_type;/* type of file */char d_name[256];/* filename */};
Embora esse link possa responder à pergunta, é melhor incluir aqui as partes essenciais da resposta e fornecer o link para referência. As respostas somente para links podem se tornar inválidas se a página vinculada for alterada. - Da avaliação
ice1000 28/06
@ ice1000 Sério? Esta Q&A é de 2009
Tim
8
Confira esta classe que usa a API do win32. Apenas construa uma instância fornecendo a foldernamepartir da qual você deseja a listagem e chame o getNextFilemétodo para obter a próxima a filenamepartir do diretório Eu acho que precisa windows.he stdio.h.
classFileGetter{
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;}};
Além disso, às vezes é bom ir direto à fonte (trocadilho intencional). Você pode aprender muito observando as entranhas de alguns dos comandos mais comuns no Linux. Eu configurei um espelho simples dos coreutils do GNU no github (para leitura).
-1. string2wchar_tretorna o endereço de uma variável local. Além disso, você provavelmente deve usar os métodos de conversão disponíveis no WinAPI em vez de escrever seus próprios.
Daniel Kamil Kozar
3
Essa implementação realiza seu objetivo, preenchendo dinamicamente uma matriz de seqüências de caracteres com o conteúdo do diretório especificado.
int exploreDirectory(constchar*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);return0;}
Como eu chamaria isso? Estou recebendo segfaults quando tento executar esta função no primeiro ifbloco. Eu estou chamando-lo comchar **list; int numItems; exploreDirectory("/folder",list, numItems);
Hal T
2
Isso funciona para mim. Me desculpe se não consigo me lembrar da fonte. Provavelmente é de uma página de manual.
você pode obter todos os arquivos diretos em seu diretório raiz usando std :: experimental :: filesystem :: directory_iterator (). Em seguida, leia o nome desses arquivos de caminho.
Esta resposta deve funcionar para usuários do Windows que tiveram problemas ao trabalhar com o Visual Studio com qualquer uma das outras respostas.
Faça o download do arquivo dirent.h na página do github. Mas é melhor usar apenas o arquivo Raw dirent.h e seguir meus passos abaixo (é como eu o fiz funcionar).
Coloque o void filefinder()método abaixo no seu código e chame-o da sua mainfunção ou edite a função como deseja usá-lo.
#include<stdio.h>#include<string.h>#include"dirent.h"string path ="C:/folder";//Put a valid path here for foldervoid 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);}
EDIT: Essa resposta deve ser considerada um hack, mas realmente funciona (embora de uma maneira específica da plataforma) se você não tiver acesso a soluções mais elegantes.
Não tenho permissão para executar o comando 'ls' e analisar os resultados de dentro do meu programa. Eu sabia que haveria alguém que iria enviar algo assim ...
yyny
1
Como os arquivos e subdiretórios de um diretório geralmente são armazenados em uma estrutura em árvore, uma maneira intuitiva é usar o algoritmo DFS para percorrer recursivamente cada um deles. Aqui está um exemplo no sistema operacional Windows, usando funções básicas de arquivo em io.h. Você pode substituir essas funções em outra plataforma. O que quero expressar é que a idéia básica do DFS atende perfeitamente a esse problema.
#include<io.h>#include<iostream.h>#include<string>usingnamespace std;voidTraverseFilesUsingDFS(conststring& 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 dirif(handle ==-1){
cerr <<"folder path not exist: "<< folder_path << endl;exit(-1);}//iteratively check each file or sub_directory in current folderdo{string file_name=file_info.name;//from char array to string//check whtether it is a sub direcotry or a fileif(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);}
Tentei seguir o exemplo dado nas duas respostas e pode valer a pena notar que parece que std::filesystem::directory_entryfoi alterado para não ter uma sobrecarga do <<operador. Em vez de std::cout << p << std::endl;, tive que usar o seguinte para poder compilar e fazê-lo funcionar:
Se você souber que usará apenas multibyte, poderá usar WIN32_FIND_DATAA, FindFirstFileAe FindNextFileA. Então não haverá necessidade de converter resultado em multibyte ou Entrada em unicode.
Kiran Thilak
0
Apenas algo que eu quero compartilhar e obrigado pelo material de leitura. Brinque um pouco com a função para entendê-la. Você pode gostar. e significava extensão, p é para caminho e s é para separador de caminho.
Se o caminho for passado sem terminar o separador, um separador será anexado ao caminho. Para a extensão, se uma string vazia for inserida, a função retornará qualquer arquivo que não tenha uma extensão em seu nome. Se uma única estrela foi inserida, todos os arquivos no diretório serão retornados. Se e comprimento for maior que 0, mas não for um único *, um ponto será anexado a e se e não contiver um ponto na posição zero.
Para um valor retornado. Se um mapa de tamanho zero for retornado, nada foi encontrado, mas o diretório foi aberto corretamente. Se o índice 999 estiver disponível no valor de retorno, mas o tamanho do mapa for apenas 1, isso significava que havia um problema ao abrir o caminho do diretório.
Observe que, para eficiência, esta função pode ser dividida em três funções menores. Além disso, você pode criar uma função de chamada que detectará qual função será chamada com base na entrada. Por que isso é mais eficiente? Disse que se você vai pegar tudo o que é um arquivo, nesse método, a subfunção criada para pegar todos os arquivos irá apenas pegar todos os arquivos e não precisará avaliar nenhuma outra condição desnecessária toda vez que encontrar um arquivo.
Isso também se aplica a quando você pega arquivos que não têm extensão. Uma função construída específica para esse fim avaliaria apenas o clima se o objeto encontrado for um arquivo e, em seguida, se o nome do arquivo possui ou não um ponto.
A economia pode não ser muito se você ler apenas diretórios com pouco arquivo. Mas se você estiver lendo uma grande quantidade de diretório ou se o diretório tiver centenas de milhares de arquivos, pode ser uma grande economia.
#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 ="",unsignedchar 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(constauto&p : m){
std::cout <<"m["<< p.first <<"] = "<< p.second << std::endl;}}int main(){
std::map<int, std::string> k = getFile("./","");
printMap(k);return0;}
Isso funcionou para mim. Ele grava um arquivo com apenas os nomes (sem caminho) de todos os arquivos. Em seguida, ele lê o arquivo txt e o imprime para você.
stat()
erro 'sem esse arquivo ou diretório' quando o nome do arquivo for retornado porreaddir()
.Respostas:
Em tarefas pequenas e simples, não uso o boost, uso o dirent.h, que também está disponível para o Windows:
É apenas um pequeno arquivo de cabeçalho e faz a maioria das coisas simples que você precisa, sem usar uma grande abordagem baseada em modelo como impulso (sem ofensa, eu gosto de aumento!).
O autor da camada de compatibilidade do Windows é Toni Ronkko. No Unix, é um cabeçalho padrão.
ATUALIZAÇÃO 2017 :
Em C ++ 17 há agora uma maneira oficial de arquivos de lista de seu sistema de arquivos:
std::filesystem
. Há uma excelente resposta de Shreevardhan abaixo com este código-fonte:fonte
std::experimental::filesystem
, com C ++ 17 existestd::filesystem
. Veja a resposta de Shreevardhan abaixo. Portanto, não há necessidade de bibliotecas de terceiros.O C ++ 17 agora possui um
std::filesystem::directory_iterator
, que pode ser usado comoAlém disso, também
std::filesystem::recursive_directory_iterator
pode iterar os subdiretórios.fonte
namespace fs = std::experimental::filesystem;
. Parece funcionar bem embora.std::filesystem::path
parastd::cout
, as aspas estão incluídas na saída. Para evitar isso, anexe.string()
ao caminho para fazer uma conversão explícita em vez de implícita (aquistd::cout << p.string() << std::endl;
). Exemplo: coliru.stacked-crooked.com/view?id=a55ea60bbd36a8a3std::wstring
ser usado ou qual é o tipo do iterador?-lstdc++fs
, eu obteria umSIGSEGV (Address boundary error)
. Não consegui encontrar em nenhum lugar da documentação que isso fosse necessário e o vinculador também não deu nenhuma pista. Isso funcionou para ambosg++ 8.3.0
eclang 8.0.0-3
. Alguém tem alguma idéia de onde essas coisas são especificadas nos documentos / especificações?Infelizmente, o padrão C ++ não define uma maneira padrão de trabalhar com arquivos e pastas dessa maneira.
Como não existe uma maneira multiplataforma, a melhor maneira multiplataforma é usar uma biblioteca como o módulo de sistema de arquivos boost .
Método de aumento de plataforma cruzada:
Fonte da página de impulso mencionada acima.
Para sistemas baseados em Unix / Linux:
Você pode usar opendir / readdir / closedir .
Código fonte das páginas de manual acima.
Para sistemas baseados em Windows:
Você pode usar as funções FindFirstFile / FindNextFile / FindClose da API do Win32 .
Código fonte das páginas msdn acima.
fonte
FindFirstFile(TEXT("D:\\IMAGE\\MYDIRECTORY\\*"), &findFileData);
std::experimental::filesystem
, com o C ++ 17std::filesystem
, que possuem funcionalidades semelhantes às do boost (as bibliotecas são derivadas do boost). Veja a resposta de Shreevardhan abaixo.Uma função é suficiente, você não precisa usar nenhuma biblioteca de terceiros (para Windows).
PS: como mencionado por @Sebastian, você pode mudar
*.*
para*.ext
para obter apenas os arquivos EXT (ou seja, de um tipo específico) nesse diretório.fonte
std::vector<std::wstring>
ae, emfileName.c_str()
vez de um vetor de strings, que não seria compilado.Para uma solução apenas C, verifique isso. Requer apenas um cabeçalho extra:
https://github.com/cxong/tinydir
Algumas vantagens sobre outras opções:
readdir_r
quando disponível, o que significa que é (geralmente) seguro para threadsUNICODE
macrosfonte
Eu recomendo usar
glob
com este invólucro reutilizável. Ele gera umvector<string>
caminho correspondente ao arquivo que se ajusta ao padrão glob:Que pode ser chamado com um padrão curinga normal do sistema, como:
fonte
No such file or directory
. Você pode me dizer como resolver esse problema, por favor?GLOB_TILDE
comGLOB_TILDE | GLOB_MARK
e, em seguida, verificar se há caminhos que terminam em uma barra. Você precisará fazer uma modificação, se precisar.glob
.Aqui está um código muito simples no
C++11
uso daboost::filesystem
biblioteca para obter nomes de arquivos em um diretório (excluindo nomes de pastas):A saída é como:
fonte
boost::filesystem
biblioteca boost.org/doc/libs/1_58_0/libs/filesystem/doc/index.htmPor que não usar
glob()
?fonte
Eu acho que, abaixo do snippet, pode ser usado para listar todos os arquivos.
A seguir está a estrutura do diretório dir
fonte
Experimente o boost para o método x-platform
http://www.boost.org/doc/libs/1_38_0/libs/filesystem/doc/index.htm
ou apenas use o arquivo específico do seu sistema operacional.
fonte
Confira esta classe que usa a API do win32. Apenas construa uma instância fornecendo a
foldername
partir da qual você deseja a listagem e chame ogetNextFile
método para obter a próxima afilename
partir do diretório Eu acho que precisawindows.h
estdio.h
.fonte
GNU Manual FTW
http://www.gnu.org/software/libc/manual/html_node/Simple-Directory-Lister.html#Simple-Directory-Lister
Além disso, às vezes é bom ir direto à fonte (trocadilho intencional). Você pode aprender muito observando as entranhas de alguns dos comandos mais comuns no Linux. Eu configurei um espelho simples dos coreutils do GNU no github (para leitura).
https://github.com/homer6/gnu_coreutils/blob/master/src/ls.c
Talvez isso não atenda ao Windows, mas vários casos de uso de variantes do Unix podem ser encontrados usando esses métodos.
Espero que ajude...
fonte
Shreevardhan resposta funciona muito bem. Mas se você quiser usá-lo no c ++ 14, faça uma alteração
namespace fs = experimental::filesystem;
ou seja,
fonte
fonte
Espero que este código o ajude.
fonte
string2wchar_t
retorna o endereço de uma variável local. Além disso, você provavelmente deve usar os métodos de conversão disponíveis no WinAPI em vez de escrever seus próprios.Essa implementação realiza seu objetivo, preenchendo dinamicamente uma matriz de seqüências de caracteres com o conteúdo do diretório especificado.
fonte
if
bloco. Eu estou chamando-lo comchar **list; int numItems; exploreDirectory("/folder",list, numItems);
Isso funciona para mim. Me desculpe se não consigo me lembrar da fonte. Provavelmente é de uma página de manual.
fonte
você pode obter todos os arquivos diretos em seu diretório raiz usando std :: experimental :: filesystem :: directory_iterator (). Em seguida, leia o nome desses arquivos de caminho.
fonte
Esta resposta deve funcionar para usuários do Windows que tiveram problemas ao trabalhar com o Visual Studio com qualquer uma das outras respostas.
Faça o download do arquivo dirent.h na página do github. Mas é melhor usar apenas o arquivo Raw dirent.h e seguir meus passos abaixo (é como eu o fiz funcionar).
Página do Github para dirent.h para Windows: página do Github para dirent.h
Arquivo Direto não processado: Arquivo dirent.h não processado
Vá para o seu projeto e adicione um novo item ( Ctrl+ Shift+ A). Adicione um arquivo de cabeçalho (.h) e chame-o de dirent.h.
Cole o código do arquivo dirent.h bruto no seu cabeçalho.
Inclua "dirent.h" no seu código.
Coloque o
void filefinder()
método abaixo no seu código e chame-o da suamain
função ou edite a função como deseja usá-lo.fonte
Sistema chamá-lo!
Então basta ler o arquivo.
EDIT: Essa resposta deve ser considerada um hack, mas realmente funciona (embora de uma maneira específica da plataforma) se você não tiver acesso a soluções mais elegantes.
fonte
Como os arquivos e subdiretórios de um diretório geralmente são armazenados em uma estrutura em árvore, uma maneira intuitiva é usar o algoritmo DFS para percorrer recursivamente cada um deles. Aqui está um exemplo no sistema operacional Windows, usando funções básicas de arquivo em io.h. Você pode substituir essas funções em outra plataforma. O que quero expressar é que a idéia básica do DFS atende perfeitamente a esse problema.
fonte
Tentei seguir o exemplo dado nas duas respostas e pode valer a pena notar que parece que
std::filesystem::directory_entry
foi alterado para não ter uma sobrecarga do<<
operador. Em vez destd::cout << p << std::endl;
, tive que usar o seguinte para poder compilar e fazê-lo funcionar:tentar passar
p
por si próprio parastd::cout <<
resultar em um erro de sobrecarga ausente.fonte
Com base no que herohuyongtao postou e em algumas outras postagens:
http://www.cplusplus.com/forum/general/39766/
Qual é o tipo de entrada esperado de FindFirstFile?
Como converter wstring em string?
Esta é uma solução do Windows.
Como eu queria passar em std :: string e retornar um vetor de strings, tive que fazer algumas conversões.
fonte
WIN32_FIND_DATAA
,FindFirstFileA
eFindNextFileA
. Então não haverá necessidade de converter resultado em multibyte ou Entrada em unicode.Apenas algo que eu quero compartilhar e obrigado pelo material de leitura. Brinque um pouco com a função para entendê-la. Você pode gostar. e significava extensão, p é para caminho e s é para separador de caminho.
Se o caminho for passado sem terminar o separador, um separador será anexado ao caminho. Para a extensão, se uma string vazia for inserida, a função retornará qualquer arquivo que não tenha uma extensão em seu nome. Se uma única estrela foi inserida, todos os arquivos no diretório serão retornados. Se e comprimento for maior que 0, mas não for um único *, um ponto será anexado a e se e não contiver um ponto na posição zero.
Para um valor retornado. Se um mapa de tamanho zero for retornado, nada foi encontrado, mas o diretório foi aberto corretamente. Se o índice 999 estiver disponível no valor de retorno, mas o tamanho do mapa for apenas 1, isso significava que havia um problema ao abrir o caminho do diretório.
Observe que, para eficiência, esta função pode ser dividida em três funções menores. Além disso, você pode criar uma função de chamada que detectará qual função será chamada com base na entrada. Por que isso é mais eficiente? Disse que se você vai pegar tudo o que é um arquivo, nesse método, a subfunção criada para pegar todos os arquivos irá apenas pegar todos os arquivos e não precisará avaliar nenhuma outra condição desnecessária toda vez que encontrar um arquivo.
Isso também se aplica a quando você pega arquivos que não têm extensão. Uma função construída específica para esse fim avaliaria apenas o clima se o objeto encontrado for um arquivo e, em seguida, se o nome do arquivo possui ou não um ponto.
A economia pode não ser muito se você ler apenas diretórios com pouco arquivo. Mas se você estiver lendo uma grande quantidade de diretório ou se o diretório tiver centenas de milhares de arquivos, pode ser uma grande economia.
fonte
fonte
Isso funcionou para mim. Ele grava um arquivo com apenas os nomes (sem caminho) de todos os arquivos. Em seguida, ele lê o arquivo txt e o imprime para você.
fonte