Ein Hinweis zum Navigieren in der Dateihierarchie mit fts.
Erstellen Sie ein Beispielprogramm, das das durch das Argument angegebene Verzeichnis durchsucht und die Größe und den Pfadnamen ausgibt.
sample.cpp
#include <cstdio>
#include <fts.h>
#include <sys/stat.h>
int main(int argc, char** argv)
{
if (argc != 2) {
std::fprintf(stderr, "Usage: %s <dir>\n", argv[0]);
return -1;
}
char* const paths[] = {argv[1], nullptr};
FTS* fts = fts_open(paths, 0, nullptr);
if (fts == nullptr) {
std::fprintf(stderr, "open failed.\n");
return -1;
}
FTSENT* ent = nullptr;
while ((ent = fts_read(fts)) != nullptr) {
std::printf("%-5lu %s\n", ent->fts_statp->st_size, ent->fts_path);
}
if (fts_close(fts) != 0) {
std::fprintf(stderr, "close failed.\n");
return -1;
}
return 0;
}
Der Größenpfad des Verzeichnisses und der Datei kann rekursiv ausgegeben werden.
$ g++ -std=c++14 sample.cpp -o sample
$ ./sample testdir
4096 testdir
4096 testdir/subdir
114 testdir/subdir/fff.txt
110 testdir/subdir/eee.txt
49 testdir/subdir/ddd.txt
4096 testdir/subdir
64 testdir/bbb.txt
48 testdir/aaa.txt
8 testdir/ccc.txt
4096 testdir
Es scheint möglich zu sein, die Reihenfolge des Durchlaufens der Dateihierarchie zu ändern, indem Sie fts_open einen Funktionszeiger geben.
$ man fts
...
FTS *fts_open(char * const *path_argv, int options,
int (*compar)(const FTSENT **, const FTSENT **));
...
The argument compar() specifies a user-defined function which may be used to order the traversal of the hierarchy.
It takes two pointers to pointers to FTSENT structures as arguments and should return a negative value, zero, or a positive value to indicate if the file referenced by its first argument comes before, in any order with respect to, or after, the file referenced by its second argument.
...
Ändern Sie es also so, dass es einen Funktionszeiger gibt, sodass die Größe in aufsteigender Reihenfolge ausgegeben wird, und führen Sie es erneut aus.
sample2.cpp
#include <cstdio>
#include <fts.h>
#include <sys/stat.h>
static int compar(const FTSENT** rhs, const FTSENT** lhs)
{
const FTSENT* r = *rhs;
const FTSENT* l = *lhs;
return (r->fts_statp->st_size - l->fts_statp->st_size);
}
int main(int argc, char** argv)
{
if (argc != 2) {
std::fprintf(stderr, "Usage: %s <dir>\n", argv[0]);
return -1;
}
char* const paths[] = {argv[1], nullptr};
FTS* fts = fts_open(paths, 0, compar);
if (fts == nullptr) {
std::fprintf(stderr, "open failed.\n");
return -1;
}
FTSENT* ent = nullptr;
while ((ent = fts_read(fts)) != nullptr) {
std::printf("%-5lu %s\n", ent->fts_statp->st_size, ent->fts_path);
}
if (fts_close(fts) != 0) {
std::fprintf(stderr, "close failed.\n");
return -1;
}
return 0;
}
Dateien im Verzeichnis werden jetzt in aufsteigender Reihenfolge der Größe ausgegeben.
$ g++ -std=c++14 sample2.cpp -o sample2
$ ./sample2 testdir/
4096 testdir/
8 testdir/ccc.txt
48 testdir/aaa.txt
64 testdir/bbb.txt
4096 testdir/subdir
49 testdir/subdir/ddd.txt
110 testdir/subdir/eee.txt
114 testdir/subdir/fff.txt
4096 testdir/subdir
4096 testdir/
Recommended Posts