Une note sur la façon de naviguer dans la hiérarchie de fichiers à l'aide de fts.
Créez un exemple de programme qui analyse le répertoire donné par l'argument et affiche la taille et le chemin.
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;
}
Le chemin de taille du répertoire et du fichier peut être généré de manière récursive.
$ 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
Il semble possible de changer l'ordre de parcours de la hiérarchie des fichiers en donnant à fts_open un pointeur de fonction.
$ 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.
...
Donc, modifiez-le pour donner un pointeur de fonction afin que la taille soit sortie dans l'ordre croissant, et exécutez-le à nouveau.
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;
}
Les fichiers du répertoire sont maintenant sortis par ordre croissant de taille.
$ 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