Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qdiriterator.cpp
Go to the documentation of this file.
1// Copyright (C) 2016 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
4/*!
5 \since 4.3
6 \class QDirIterator
7 \inmodule QtCore
8 \ingroup io
9 \brief The QDirIterator class provides an iterator for directory entrylists.
10
11 You can use QDirIterator to navigate entries of a directory one at a time.
12 It is similar to QDir::entryList() and QDir::entryInfoList(), but because
13 it lists entries one at a time instead of all at once, it scales better
14 and is more suitable for large directories. It also supports listing
15 directory contents recursively, and following symbolic links. Unlike
16 QDir::entryList(), QDirIterator does not support sorting.
17
18 The QDirIterator constructor takes a QDir or a directory as
19 argument. After construction, the iterator is located before the first
20 directory entry. Here's how to iterate over all the entries sequentially:
21
22 \snippet code/src_corelib_io_qdiriterator.cpp 0
23
24 Here's how to find and read all files filtered by name, recursively:
25
26 \snippet code/src_corelib_io_qdiriterator.cpp 1
27
28 The next() and nextFileInfo() functions advance the iterator and return
29 the path or the QFileInfo of the next directory entry. You can also call
30 filePath() or fileInfo() to get the current file path or QFileInfo without
31 first advancing the iterator. The fileName() function returns only the
32 name of the file, similar to how QDir::entryList() works.
33
34 Unlike Qt's container iterators, QDirIterator is uni-directional (i.e.,
35 you cannot iterate directories in reverse order) and does not allow random
36 access.
37
38 \note This class is deprecated and may be removed in a Qt release. Use
39 QDirListing instead.
40
41 \sa QDir, QDir::entryList()
42*/
43
44/*! \enum QDirIterator::IteratorFlag
45
46 This enum describes flags that you can combine to configure the behavior
47 of QDirIterator.
48
49 \value NoIteratorFlags The default value, representing no flags. The
50 iterator will return entries for the assigned path.
51
52 \value Subdirectories List entries inside all subdirectories as well.
53
54 \value FollowSymlinks When combined with Subdirectories, this flag
55 enables iterating through all subdirectories of the assigned path,
56 following all symbolic links. Symbolic link loops (e.g., "link" => "." or
57 "link" => "..") are automatically detected and ignored.
58*/
59
60#include "qdiriterator.h"
61#include "qdir_p.h"
63#include "qdirlisting.h"
65
66#include <QtCore/qset.h>
67#include <QtCore/qstack.h>
68#include <QtCore/qvariant.h>
69#if QT_CONFIG(regularexpression)
70#include <QtCore/qregularexpression.h>
71#endif
72
73#include <QtCore/private/qfilesystemiterator_p.h>
74#include <QtCore/private/qfilesystementry_p.h>
75#include <QtCore/private/qfilesystemmetadata_p.h>
76#include <QtCore/private/qfilesystemengine_p.h>
77#include <QtCore/private/qfileinfo_p.h>
78#include <QtCore/private/qduplicatetracker_p.h>
79
80#include <memory>
81#include <stack>
82#include <vector>
83
84QT_BEGIN_NAMESPACE
85
86using namespace Qt::StringLiterals;
87
89{
90public:
91 QDirIteratorPrivate(const QString &path, const QStringList &nameFilters = {},
92 QDir::Filters filters = QDir::NoFilter,
93 QDirIterator::IteratorFlags flags = QDirIterator::NoIteratorFlags)
95 { init(); }
96
97 void init()
98 {
99 it = lister.begin();
100 if (it != lister.end())
101 nextFileInfo = it->fileInfo();
102 }
103
104 void advance()
105 {
106 // Match the behavior of advance() from before porting to QDirListing,
107 // that is, even if hasNext() returns false, calling next() returns an
108 // empty string without crashing. QTBUG-130142
109 if (it == lister.end())
110 return;
111 currentFileInfo = nextFileInfo;
112 if (++it != lister.end()) {
113 nextFileInfo = it->fileInfo();
114 }
115 }
116
120 QFileInfo nextFileInfo;
121};
122
123/*!
124 Constructs a QDirIterator that can iterate over \a dir's entrylist, using
125 \a dir's name filters and regular filters. You can pass options via \a
126 flags to decide how the directory should be iterated.
127
128 By default, \a flags is NoIteratorFlags, which provides the same behavior
129 as in QDir::entryList().
130
131 The sorting in \a dir is ignored.
132
133 \note To list symlinks that point to non existing files, QDir::System must be
134 passed to the flags.
135
136 \sa hasNext(), next(), IteratorFlags
137*/
138QDirIterator::QDirIterator(const QDir &dir, IteratorFlags flags)
139 : d(new QDirIteratorPrivate(dir.path(), dir.nameFilters(), dir.filter(), flags))
140{
141}
142
143/*!
144 Constructs a QDirIterator that can iterate over \a path, with no name
145 filtering and \a filters for entry filtering. You can pass options via \a
146 flags to decide how the directory should be iterated.
147
148 By default, \a filters is QDir::NoFilter, and \a flags is NoIteratorFlags,
149 which provides the same behavior as in QDir::entryList().
150
151 \note To list symlinks that point to non existing files, QDir::System must be
152 passed to the flags.
153
154 \sa hasNext(), next(), IteratorFlags
155*/
156QDirIterator::QDirIterator(const QString &path, QDir::Filters filters, IteratorFlags flags)
157 : d(new QDirIteratorPrivate(path, {}, filters, flags))
158{
159}
160
161/*!
162 Constructs a QDirIterator that can iterate over \a path. You can pass
163 options via \a flags to decide how the directory should be iterated.
164
165 By default, \a flags is NoIteratorFlags, which provides the same behavior
166 as in QDir::entryList().
167
168 \note To list symlinks that point to non existing files, QDir::System must be
169 passed to the flags.
170
171 \sa hasNext(), next(), IteratorFlags
172*/
173QDirIterator::QDirIterator(const QString &path, IteratorFlags flags)
174 : d(new QDirIteratorPrivate(path, {}, QDir::NoFilter, flags))
175{
176}
177
178/*!
179 Constructs a QDirIterator that can iterate over \a path, using \a
180 nameFilters and \a filters. You can pass options via \a flags to decide
181 how the directory should be iterated.
182
183 By default, \a flags is NoIteratorFlags, which provides the same behavior
184 as QDir::entryList().
185
186 For example, the following iterator could be used to iterate over audio
187 files:
188
189 \snippet code/src_corelib_io_qdiriterator.cpp 2
190
191 \note To list symlinks that point to non existing files, QDir::System must be
192 passed to the flags.
193
194 \sa hasNext(), next(), IteratorFlags, QDir::setNameFilters()
195*/
196QDirIterator::QDirIterator(const QString &path, const QStringList &nameFilters,
197 QDir::Filters filters, IteratorFlags flags)
198 : d(new QDirIteratorPrivate(path, nameFilters, filters, flags))
199{
200}
201
202/*!
203 Destroys the QDirIterator.
204*/
205QDirIterator::~QDirIterator()
206{
207}
208
209/*!
210 Advances the iterator to the next entry, and returns the file path of this
211 new entry. You should first check hasNext() before using this method, to
212 avoid unexpected results.
213
214 You can call fileName() or filePath() to get the current entry's file name
215 or path, or fileInfo() to get a QFileInfo for the current entry.
216
217 Call nextFileInfo() instead of next() if you're interested in the QFileInfo.
218
219 \sa hasNext(), nextFileInfo(), fileName(), filePath(), fileInfo()
220*/
221QString QDirIterator::next()
222{
223 d->advance();
224 return d->currentFileInfo.filePath();
225}
226
227/*!
228 \since 6.3
229
230 Advances the iterator to the next entry, and returns the file info of this
231 new entry. You should first check hasNext() before using this method, to
232 avoid unexpected results.
233
234 You can call fileName() or filePath() to get the current entry's file name
235 or path, or fileInfo() to get a QFileInfo for the current entry.
236
237 Call next() instead of nextFileInfo() when all you need is the filePath().
238
239 \sa hasNext(), fileName(), filePath(), fileInfo()
240*/
241QFileInfo QDirIterator::nextFileInfo()
242{
243 d->advance();
244 return d->currentFileInfo;
245}
246
247/*!
248 Returns \c true if there is at least one more entry in the directory;
249 otherwise, false is returned.
250
251 \sa next(), nextFileInfo(), fileName(), filePath(), fileInfo()
252*/
253bool QDirIterator::hasNext() const
254{
255 return d->it != d->lister.end();
256}
257
258/*!
259 Returns the file name for the current directory entry, without the path
260 prepended.
261
262 This function is convenient when iterating a single directory. When using
263 the QDirIterator::Subdirectories flag, you can use filePath() to get the
264 full path.
265
266 \sa filePath(), fileInfo()
267*/
268QString QDirIterator::fileName() const
269{
270 return d->currentFileInfo.fileName();
271}
272
273/*!
274 Returns the full file path for the current directory entry.
275
276 \sa fileInfo(), fileName()
277*/
278QString QDirIterator::filePath() const
279{
280 return d->currentFileInfo.filePath();
281}
282
283/*!
284 Returns a QFileInfo for the current directory entry.
285
286 \sa filePath(), fileName()
287*/
288QFileInfo QDirIterator::fileInfo() const
289{
290 return d->currentFileInfo;
291}
292
293/*!
294 Returns the base directory of the iterator.
295*/
296QString QDirIterator::path() const
297{
298 return d->lister.iteratorPath();
299}
300
301QT_END_NAMESPACE
QDirIteratorPrivate(const QString &path, const QStringList &nameFilters={}, QDir::Filters filters=QDir::NoFilter, QDirIterator::IteratorFlags flags=QDirIterator::NoIteratorFlags)
QDirListing::const_iterator it