[LINUX] J'ai suivi la mise en place de la commande du (première moitié)

introduction

du est une commande pour afficher la capacité du répertoire. Si vous l'utilisez sans options, il affichera toutes les capacités du répertoire sous le répertoire courant. Cette fois, je vais suivre l'implémentation pour voir comment la fonction est réalisée.

Attendu

En tant que comportement, ce serait bien s'il y avait une fonction pour tracer le répertoire et y ajouter la taille du fichier. Pour cela, les fonctions suivantes sont susceptibles d'être nécessaires.

  1. Suivez les répertoires et fichiers dans l'ordre
  2. Obtenez la taille du fichier
  3. Additionnez la taille du fichier dans le répertoire

Regardons la mise en œuvre, en nous concentrant sur la façon dont ces fonctionnalités sont réalisées.

Suivez la mise en œuvre

Cette fois, nous allons regarder le code source de du.c inclus dans GNU coreutils. La fonction principale appelle du_files ().

python


/* Recursively print the sizes of the directories (and, if selected, files)
   named in FILES, the last entry of which is NULL.
   BIT_FLAGS controls how fts works.
   Return true if successful.  */

static bool
du_files (char **files, int bit_flags)
{
  bool ok = true;

  if (*files)
    {
      FTS *fts = xfts_open (files, bit_flags, NULL); //(1)

      while (1)
        {
          FTSENT *ent;

          ent = fts_read (fts); //(2)
          if (ent == NULL)
            {
              if (errno != 0)
                {
                  error (0, errno, _("fts_read failed"));
                  ok = false;
                }
              break;
            }
          FTS_CROSS_CHECK (fts);
          ok &= process_file (fts, ent); //(3)
        }

      if (fts_close (fts) != 0)
        {
          error (0, errno, _("fts_close failed"));
          ok = false;
        }
    }

  return ok;
}

Le traitement effectué ici est le suivant.

(1). Récupérez la structure FTS du nom de fichier avec xfts_open (). (2). Récupérez la structure FTSENT de la structure FTS avec fts_read (). (3). Appelez process_file () et revenez à (2).

xfts_open() Xfts_open () dans (1) est un wrapper pour fts_open () et en interne fts_open () est appelé. L'argument passé à xfts_open () est le nom du fichier. Ce nom de fichier est spécifié par l'argument de ligne de commande, et s'il n'y a pas d'argument, le répertoire courant est passé. La structure FTS obtenue par xfts_open () est un handle de la hiérarchie des fichiers. Le champ a une structure FTSENT qui représente des informations sur le fichier et a la position actuelle et les structures FTSENT enfant. Chaque fois que vous appelez fts_read () dans (2), ils changent et suivent la hiérarchie des fichiers (voir ci-dessous).

fts_read() Dans (2) fts_read (), la structure FTSENT à la position actuelle est obtenue à partir de la structure FTS. La structure FTSENT contient les champs suivants (fts).

python


typedef struct _ftsent {
    unsigned short fts_info;     /*Drapeaux pour les structures FTSENT*/
    char          *fts_accpath;  /*Chemin d'accès*/
    char          *fts_path;     /*Chemin racine*/
    short          fts_pathlen;  /* fts_longueur du trajet*/
    char          *fts_name;     /*nom de fichier*/
    short          fts_namelen;  /* fts_longueur du nom*/
    short          fts_level;    /*profondeur(-1 〜 N) */
    int            fts_errno;    /*Numéro d'erreur de fichier*/
    long           fts_number;   /*Nombre local*/
    void          *fts_pointer;  /*Numéro d'adresse locale*/
    struct ftsent *fts_parent;   /*Dossier Parent*/
    struct ftsent *fts_link;     /*La structure de fichiers suivante*/
    struct ftsent *fts_cycle;    /*Structure en circulation*/
    struct stat   *fts_statp;    /* stat(2)Information*/
} FTSENT;

La taille du fichier est en fts_stap (stat).

python


struct stat {
    dev_t     st_dev;     /*ID de l'appareil sur lequel se trouve le fichier*/
    ino_t     st_ino;     /*numéro d'inode*/
    mode_t    st_mode;    /*Protection d'accès*/
    nlink_t   st_nlink;   /*Nombre de liens physiques*/
    uid_t     st_uid;     /*ID utilisateur du propriétaire*/
    gid_t     st_gid;     /*ID de groupe du propriétaire*/
    dev_t     st_rdev;    /*Reference de l'appareil(Pour les fichiers spéciaux) */
    off_t     st_size;    /*Taille globale(Unité d'octet) */
    blksize_t st_blksize; /*Système de fichiers I/En O
Taille de bloc*/
    blkcnt_t  st_blocks;  /*Nombre de blocs 512B alloués*/
};

Par conséquent, la taille du fichier peut être obtenue en traçant la structure statistique à partir de la structure FTSENT.

Maintenant, la structure FTSENT a été obtenue par fts_read () dans (2). Puisque fts_read () suit automatiquement la hiérarchie des fichiers, il semble que la commande du puisse être implémentée en appelant à plusieurs reprisesfts_read ()et en totalisant la taille du fichier. Et le processus de totalisation de la taille du fichier se fait par process_file () dans (3).

Suivez le dossier

Maintenant, avant d'entrer dans l'explication de (3), voyons l'opération de traçage de la hiérarchie des fichiers par fts_read (). Vérifiez l'opération avec le code suivant (Lire les ls de FreeBSD Faisons des ls avec fts (3) ~).

python


#include <stdio.h>
#include <stdlib.h>
#include <fts.h>

int main (int argc, char *argv[])
{
        FTS *ftsp;
        FTSENT *p;
        static char dot[] = ".";
        static char *dotav[] = {dot, NULL};

        if (argc == 1)
                argv = dotav;
        else
                argv++;
        ftsp = fts_open(argv, 0, NULL);
        while((p = fts_read(ftsp)) != NULL) {
                printf("%s\n", p->fts_path);
        }
        fts_close(ftsp);

        exit(EXIT_SUCCESS);
}

Ce code est une implémentation de la commande ls utilisant la fonction fts. Tous les fichiers et répertoires du répertoire sont affichés. Le fts_read () dans l'instruction while suit la hiérarchie des fichiers, et le p-> fts_path affiche le nom du fichier. Le résultat de l'exécution est le suivant.

$ ./ls 
.
./dir1
./dir1/file3
./dir1/file4
./dir1/dir2
./dir1/dir2/file5
./dir1/dir2
./dir1
./ls.c
./ls
./file2
./file1
.

L'ordre d'affichage est le suivant. dir.jpeg

Vous pouvez voir que la profondeur est priorisée, le fichier est parcouru une fois et le répertoire est parcouru deux fois.

A continué

La prochaine fois verra le processus de process_file () dans (3).

Recommended Posts

J'ai suivi la mise en place de la commande du (première moitié)
J'ai suivi la mise en place de la commande du (seconde moitié)
J'ai lu l'implémentation de range (Objects / rangeobject.c)
[Linux] J'ai essayé de résumer les commandes de confirmation des ressources
First Python 3 ~ Le début de la répétition ~
J'ai étudié le mécanisme de connexion flask!
[Python] J'ai expliqué en détail la théorie et la mise en œuvre de la régression logistique
[Python] J'ai expliqué en détail la théorie et la mise en œuvre de l'arbre de décision
Obtenez le premier élément du jeu de requêtes
J'ai fait réfléchir AI aux paroles de Genshi Yonezu (implémentation)
J'ai essayé de résumer la méthode de mise en œuvre fréquemment utilisée de pytest-mock
J'ai utilisé la commande coupe du monde pour vérifier le résultat de la Coupe du monde.
Je souhaite laisser une commande arbitraire dans l'historique des commandes de Shell
J'ai vérifié le contenu du volume du docker
J'ai essayé le serveur asynchrone de Django 3.0
J'ai essayé de résumer la commande umask
J'ai vérifié les options de copyMakeBorder d'OpenCV
Othello-De la troisième ligne de "Implementation Deep Learning" (3)
La structure des dossiers de Flask est résumée
Je ne connaissais pas les bases de Python
Version Migemo de la commande: find ,: mfind
Le modèle de projet Python auquel je pense.
Lire l'implémentation de la minuterie globale ARM
Notez l'achèvement d'une commande chronophage
AtCoder Revue des questions précédentes (première moitié de 12 / 8,9)
Othello-De la troisième ligne de "Implementation Deep Learning" (2)
J'ai essayé de comprendre attentivement la fonction d'apprentissage dans le réseau de neurones sans utiliser la bibliothèque d'apprentissage automatique (première moitié)
J'ai créé une commande appdo pour exécuter des commandes dans le contexte de l'application
[Python] J'ai expliqué en détail la théorie et l'implémentation de la machine à vecteurs de support (SVM).
J'ai essayé la fonction de tableau croisé dynamique des pandas
J'ai essayé l'analyse par grappes de la carte météo
J'ai résolu le problème le plus profond d'Hiroshi Yuki.
Pourquoi l'implémentation Python d'ISUCON 5 a utilisé Bottle
J'ai essayé l'analyse du SRAS avant le virus corona
J'ai vérifié la liste des touches de raccourci de Jupyter
J'ai essayé la programmation python pour la première fois.
J'ai essayé de corriger la forme trapézoïdale de l'image
Essayez Progate Free Edition [Python I]
J'ai vérifié la période de rétention de session de django
L'histoire de la mauvaise lecture de la ligne d'échange de la commande supérieure
J'ai vérifié la vitesse de traitement de la numpy unidimensionnelle
J'ai essayé Mind Meld pour la première fois
J'ai touché certaines des nouvelles fonctionnalités de Python 3.8 ①
J'ai lu et implémenté les variantes de UKR
Je souhaite personnaliser l'apparence de zabbix
J'ai essayé d'utiliser le filtre d'image d'OpenCV
J'ai essayé de vectoriser les paroles de Hinatazaka 46!
Deuxième moitié de la première journée d'étude de Python Essayez d'utiliser l'API Twitter avec Bottle
[First data science ⑥] J'ai essayé de visualiser le prix du marché des restaurants à Tokyo
J'ai jeté un œil au contenu de sklearn (scikit-learn) (1) ~ Qu'en est-il de l'implémentation de CountVectorizer? ~
J'ai couru le tutoriel TensorFlow avec des commentaires (premier réseau de neurones: le début du problème de classification)
Je souhaite également utiliser les commandes Linux à l'invite de commande! Utilisez les commandes Linux à l'invite de commande au lieu de Git Bash