Jak rekurencyjnie przeglądać każdy plik / katalog w standardowym C ++?
c++
filesystems
robottobor
źródło
źródło
Odpowiedzi:
W standardowym C ++ technicznie nie da się tego zrobić, ponieważ standardowy C ++ nie ma koncepcji katalogów. Jeśli chcesz trochę rozszerzyć swoją sieć, możesz spojrzeć na użycie Boost.FileSystem . Zostało to zaakceptowane do włączenia do TR2, więc daje to największą szansę na utrzymanie implementacji jak najbliżej standardu.
Przykład zaczerpnięty prosto ze strony:
źródło
Począwszy od C ++ 17,
<filesystem>
nagłówek i zakres-for
, możesz po prostu zrobić to:Od C ++ 17
std::filesystem
jest częścią biblioteki standardowej i można go znaleźć w<filesystem>
nagłówku (nie jest już „eksperymentalny”).źródło
using
, użyjnamespace
zamiast tego.W przypadku korzystania z interfejsu API Win32 można używać funkcji FindFirstFile i FindNextFile .
http://msdn.microsoft.com/en-us/library/aa365200(VS.85).aspx
W przypadku cyklicznego przeglądania katalogów należy sprawdzić wszystkie atrybuty WIN32_FIND_DATA.dwFileAttributes, aby sprawdzić, czy bit FILE_ATTRIBUTE_DIRECTORY jest ustawiony. Jeśli bit jest ustawiony, możesz rekurencyjnie wywołać funkcję z tym katalogiem. Alternatywnie możesz użyć stosu, aby zapewnić ten sam efekt wywołania rekurencyjnego, ale uniknąć przepełnienia stosu dla bardzo długich drzew ścieżek.
źródło
Możesz to jeszcze bardziej uprościć dzięki nowej gamie opartej na C ++ 11
for
i Boost :źródło
Szybkim rozwiązaniem jest użycie biblioteki Dirent.h języka C.
Działający fragment kodu z Wikipedii:
źródło
Oprócz wspomnianego powyżej boost :: filesystem możesz chcieć sprawdzić wxWidgets :: wxDir i Qt :: QDir .
Zarówno wxWidgets, jak i Qt są open source, wieloplatformowymi frameworkami C ++.
wxDir
zapewnia elastyczny sposób przechodzenia między plikami rekurencyjnie przy użyciuTraverse()
lub prostszejGetAllFiles()
funkcji. Możesz również zaimplementować przechodzenie z funkcjamiGetFirst()
iGetNext()
(zakładam, że Traverse () i GetAllFiles () są opakowaniami, które ostatecznie używają funkcji GetFirst () i GetNext ()).QDir
zapewnia dostęp do struktur katalogów i ich zawartości. Istnieje kilka sposobów przeglądania katalogów za pomocą QDir. Możesz iterować po zawartości katalogu (w tym podkatalogów) za pomocą QDirIterator, którego instancja została utworzona z flagą QDirIterator :: Subdirectories. Innym sposobem jest użycie funkcji GetEntryList () QDir i zaimplementowanie przechodzenia rekurencyjnego.Oto przykładowy kod (pobrany stąd # Przykład 8-5), który pokazuje, jak iterować po wszystkich podkatalogach.
źródło
Boost :: filesystem zapewnia recursive_directory_iterator, co jest dość wygodne w przypadku tego zadania:
źródło
Możesz używać
ftw(3)
lubnftw(3)
do poruszania się po hierarchii systemu plików w C lub C ++ w systemach POSIX .źródło
nftw()
użytku.Ty nie. W standardzie C ++ nie ma koncepcji katalogów. Od implementacji zależy, czy ciąg znaków zostanie przekształcony w uchwyt pliku. Zawartość tego ciągu i to, na co jest mapowany, zależy od systemu operacyjnego. Pamiętaj, że C ++ może być użyty do napisania tego systemu operacyjnego, więc jest używany na poziomie, na którym pytanie, jak iterować przez katalog, nie jest jeszcze zdefiniowane (ponieważ piszesz kod zarządzania katalogami).
Zajrzyj do dokumentacji interfejsu API systemu operacyjnego, aby dowiedzieć się, jak to zrobić. Jeśli chcesz być przenośny, będziesz musiał mieć kilka #ifdef dla różnych systemów operacyjnych.
źródło
Prawdopodobnie byłbyś najlepszy z eksperymentalnym systemem plików boost lub c ++ 14. JEŚLI analizujesz katalog wewnętrzny (tj. Używany przez program do przechowywania danych po zamknięciu programu), utwórz plik indeksowy, który będzie zawierał indeks zawartości pliku. Nawiasem mówiąc, prawdopodobnie będziesz musiał użyć boost w przyszłości, więc jeśli go nie masz, zainstaluj go! Po drugie, możesz użyć kompilacji warunkowej, np .:
Kod dla każdego przypadku pochodzi z https://stackoverflow.com/a/67336/7077165
źródło
Musisz wywołać funkcje specyficzne dla systemu operacyjnego do przechodzenia przez system plików, takie jak
open()
ireaddir()
. Standard C nie określa żadnych funkcji związanych z systemem plików.źródło
Jesteśmy w 2019 roku. Mamy bibliotekę standardowych systemów plików w
C++
. PlikFilesystem library
Zapewnia zaplecze do przeprowadzania operacji na systemie plików i ich składników, takich jak ścieżki, zwykłych plików i katalogów.Pod tym linkiem znajduje się ważna uwaga, jeśli rozważasz problemy z przenoszeniem. To mówi:
Biblioteka systemu plików została pierwotnie opracowana jako
boost.filesystem
, została opublikowana jako specyfikacja techniczna ISO / IEC TS 18822: 2015, a ostatecznie połączona z ISO C ++ od C ++ 17. Implementacja przyspieszenia jest obecnie dostępna na większej liczbie kompilatorów i platform niż biblioteka C ++ 17.@ adi-shavit odpowiedział na to pytanie, gdy było ono częścią std :: experimental i zaktualizował tę odpowiedź w 2017 roku. Chcę podać więcej szczegółów na temat biblioteki i pokazać bardziej szczegółowy przykład.
std :: filesystem :: recursive_directory_iterator to
LegacyInputIterator
iteracja po elementach directory_entry katalogu i rekurencyjnie po wpisach wszystkich podkatalogów. Kolejność iteracji jest nieokreślona, z wyjątkiem tego, że każda pozycja katalogu jest odwiedzana tylko raz.Jeśli nie chcesz rekurencyjnie iterować po wpisach podkatalogów, powinieneś użyć directory_iterator .
Oba iteratory zwracają obiekt directory_entry .
directory_entry
ma różne funkcje przydatne członków jakis_regular_file
,is_directory
,is_socket
,is_symlink
itdpath()
funkcja członek zwraca obiekt std :: :: ścieżki systemu plików i może być używana do pobieraniafile extension
,filename
,root name
.Rozważ poniższy przykład. Używam
Ubuntu
i skompilowane go na terminal za pomocąg ++ example.cpp --std = c ++ 17 -lstdc ++ fs -Wall
źródło
Ty nie. Standardowy C ++ nie ujawnia koncepcji katalogu. W szczególności nie daje możliwości wyświetlenia wszystkich plików w katalogu.
Okropnym hackiem byłoby użycie wywołań system () i przeanalizowanie wyników. Najbardziej rozsądnym rozwiązaniem byłoby użycie jakiejś wieloplatformowej biblioteki, takiej jak Qt lub nawet POSIX .
źródło
Możesz użyć
std::filesystem::recursive_directory_iterator
. Ale uwaga, obejmuje to symboliczne (miękkie) linki. Jeśli chcesz ich uniknąć, możesz użyćis_symlink
. Przykładowe użycie:źródło
Jeśli korzystasz z systemu Windows, możesz używać FindFirstFile razem z interfejsem API FindNextFile. Możesz użyć FindFileData.dwFileAttributes, aby sprawdzić, czy podana ścieżka jest plikiem lub katalogiem. Jeśli jest to katalog, możesz rekurencyjnie powtórzyć algorytm.
Tutaj utworzyłem kod, który zawiera listę wszystkich plików na komputerze z systemem Windows.
http://dreams-soft.com/projects/traverse-directory
źródło
Spacer po drzewie plików
ftw
to rekurencyjny sposób umieszczenia ściany w całym drzewie katalogów w ścieżce. Więcej szczegółów tutaj .UWAGA: Możesz również użyć
fts
tego, który może pomijać ukryte pliki, takie jak.
lub..
lub.bashrc
wyjście wygląda następująco:
Powiedzmy, że jeśli chcesz dopasować nazwę pliku (na przykład: wyszukiwanie wszystkich
*.jpg, *.jpeg, *.png
plików.) Do określonych potrzeb, użyjfnmatch
.źródło