Linux / Commande stat : lire les tailles, droits, inode et dates

stat affiche les métadonnées d’un fichier : taille, permissions, propriétaire, inode, liens, allocation et horodatages. Avec GNU stat, utilisez stat -c '%s' fichier pour sa taille en octets et stat -f chemin pour les informations du système de fichiers qui contient ce chemin.

Ce guide concerne GNU Coreutils. Les variantes de stat fournies par d’autres systèmes ou certains shells peuvent utiliser d’autres options. Un inode est la structure qui porte les métadonnées d’un fichier dans son système de fichiers ; son numéro est utile pour distinguer un objet de ses différents noms.

Choisir stat, ls ou file

Besoin Outil adapté
Parcourir des noms et comparer rapidement des entrées. ls -l et ses options.
Lire des champs précis de métadonnées ou de système de fichiers. stat avec un format explicite.
Estimer le format du contenu et son encodage. file, qui examine notamment les octets.

Le guide de ls explique le format long, tandis que le guide de file traite de la classification du contenu. stat interroge des métadonnées ; il ne vérifie pas que les données du document sont valides.

type -a stat
stat --version
stat --help
stat -- ./rapport.txt
stat -- ./src ./tests

Les cibles doivent exister. Protégez les chemins avec espaces par des guillemets et utilisez -- pour terminer les options. Si un alias ou une fonction masque la version GNU, env stat permet de rechercher un programme externe dans PATH.

Lire les champs de la sortie détaillée

La présentation exacte dépend du système, de la version et de la locale. Cherchez les champs suivants plutôt que leur position fixe dans une ligne :

Champ Signification
File Nom examiné, éventuellement accompagné de la cible d’un lien.
Size Taille logique du fichier, en octets pour un fichier ordinaire.
Blocks Nombre d’unités allouées, à interpréter avec la taille de leur unité.
IO Block Indication de taille de transfert favorable aux entrées-sorties ; ce n’est pas l’unité de Blocks.
Device et Inode Identifiants du système de fichiers contenant l’objet et de l’inode.
Links Nombre de liens physiques vers cet inode.
Access avec un mode Permissions en octal et sous forme symbolique, distinctes de la date Access.
Uid et Gid Identifiant utilisateur, ou UID, et identifiant de groupe, ou GID, avec les noms disponibles.
Access, Modify, Change, Birth Horodatages d’accès, de modification, de changement d’état et de création si disponible.

Une lecture de stat n’est pas un instantané transactionnel d’un arbre entier. Un programme peut remplacer ou modifier un fichier entre deux observations. Les nombres et noms d’utilisateurs affichés correspondent à l’environnement de lecture, qui peut différer dans un conteneur ou sur un autre système.

Comprendre taille, blocs et identité du fichier

Distinguer taille logique et allocation

stat -c 'taille=%s blocs=%b unite=%B transfert=%o' -- ./rapport.txt

%s donne la taille logique, %b le nombre de blocs alloués et %B la taille en octets de l’unité utilisée par %b. Leur produit %b × %B exprime l’allocation rapportée. Sous Linux, l’unité de la structure système correspond normalement à 512 octets ; lire %B évite de la confondre avec le bloc de transfert %o.

Un fichier creux, aussi appelé sparse file, peut représenter une grande taille logique avec peu de blocs alloués. La compression, le partage de blocs et les détails du stockage empêchent aussi de déduire un coût physique exclusif à partir d’un seul champ. Le guide de du et des tailles apparentes ou allouées explique les critères de comparaison.

La taille d’un répertoire décrit sa propre structure, pas la somme de tous ses descendants. Sur des interfaces virtuelles comme procfs ou sysfs, une taille affichée peut aussi différer du nombre d’octets qu’une lecture fournira. Le manuel Linux sur les informations d’inode précise les champs et ces exceptions.

Reconnaître deux noms liés au même inode

Dans un emplacement où demo-stat n’existe pas, cet exercice Bash crée un fichier et un second lien physique vers lui. Il nécessite un système de fichiers permettant les liens physiques :

(
  mkdir -- demo-stat || exit 1
  printf '%s\n' 'ABC' > demo-stat/rapport.txt
  ln -- demo-stat/rapport.txt demo-stat/autre-nom.txt || exit 1
  stat -c 'nom=%n taille=%s appareil=%d inode=%i liens=%h' -- demo-stat/rapport.txt demo-stat/autre-nom.txt
)

Les deux lignes doivent montrer une taille de 4 octets pour ABC suivi d’un saut de ligne, et les mêmes identifiants d’appareil et d’inode. Dans ce nouvel exercice sans autre lien créé en parallèle, le compteur de liens doit être 2. Les deux noms désignent les mêmes données ; le second n’est pas une copie indépendante.

Le numéro d’inode n’est pas unique à travers tous les systèmes de fichiers et peut être réutilisé après la disparition d’un objet. Comparez au moins appareil et inode, en tenant compte du moment de l’observation. Une différence de nom ne prouve pas une différence de données.

Les objets de démonstration restent sur disque après le bloc. Inspectez le dossier avant de retirer cet exercice. Retirer un seul des deux noms n’efface pas immédiatement les données tant que l’autre lien reste ; les fichiers ouverts peuvent également prolonger la durée de vie de l’objet.

Distinguer atime, mtime, ctime et Birth

Temps Ce qu’il décrit Limite d’interprétation
atime Dernier accès aux données. Une lecture ne le met pas forcément à jour immédiatement, selon les options de montage et d’ouverture.
mtime Dernière modification des données. Peut aussi être fixé par un outil de restauration ou de réglage des dates.
ctime Dernier changement d’état de l’inode. Écriture, changement de mode, propriétaire ou nombre de liens ; ce n’est pas la création.
Birth Horodatage de création fourni pour cet objet. Pas toujours disponible ; une copie peut créer un autre objet et une autre date.

Le c de ctime signifie change, pas creation. Un répertoire peut changer de mtime quand ses entrées sont créées ou retirées, même sans modification du contenu des fichiers déjà présents. La politique noatime supprime certaines mises à jour d’accès et relatime les limite ; n’utilisez pas atime comme une preuve exhaustive des lectures.

stat -c 'atime=%x
mtime=%y
ctime=%z
birth=%w' -- ./demo-stat/rapport.txt

Les minuscules donnent des dates lisibles. Quand la création est inconnue, %w affiche -. Les majuscules demandent des secondes depuis l’Epoch Unix, le 1er janvier 1970 à 00:00:00 UTC, ou temps universel coordonné :

stat -c 'atime=%X mtime=%Y ctime=%Z birth=%W' -- ./demo-stat/rapport.txt
env LC_ALL=C TZ=UTC stat -c '%y' -- ./demo-stat/rapport.txt
stat -c 'mtime=%.9Y' -- ./demo-stat/rapport.txt

%W utilise zéro lorsque Birth est inconnu : ne le convertissez pas automatiquement en date de création de 1970. Le réglage TZ du deuxième appel choisit seulement l’affichage, sans changer l’horloge. La précision demandée par %.9Y ne garantit pas que le système de fichiers enregistre réellement neuf chiffres significatifs après la seconde.

Sélectionner permissions, propriétaire et format de sortie

Choisir les champs utiles

stat -c '%a %A %n' -- ./demo-stat/rapport.txt
stat -c 'utilisateur=%U(%u) groupe=%G(%g)' -- ./demo-stat/rapport.txt
stat -c 'type=%F appareil=%d inode=%i liens=%h' -- ./demo-stat/rapport.txt

%a donne le mode en octal et %A sa forme symbolique avec le type de fichier. %U et %G donnent les noms, tandis que %u et %g donnent les identifiants numériques. L’absence d’un nom correspondant n’annule pas l’existence de l’identifiant.

Les permissions classiques ne décrivent pas forcément l’ensemble des contrôles d’accès. Les listes de contrôle d’accès, ou ACL, et des mécanismes comme SELinux (Security-Enhanced Linux) peuvent intervenir. %C demande le contexte SELinux lorsqu’il est disponible ; un affichage de mode ne suffit pas à expliquer toutes les autorisations effectives.

Différencier -c et --printf

stat -c '%n %s' -- ./demo-stat/rapport.txt ./demo-stat/autre-nom.txt
stat --printf='nom=%n\ntaille=%s\nmode=%a\n' -- ./demo-stat/rapport.txt

-c, synonyme de --format, ajoute un saut de ligne après chaque utilisation du format pour un fichier. --printf interprète les séquences comme \n mais n’ajoute pas de saut de ligne final automatique. Incluez donc les séparateurs dont votre consommateur a besoin.

%n donne le nom sans convention de protection universelle. %N donne un nom cité et peut inclure la cible d’un lien ; son style de citation peut dépendre de QUOTING_STYLE. Cette représentation est utile à l’écran, mais analyser un nom et une cible en découpant la phrase est fragile.

Examiner un lien symbolique ou sa cible

stat -- ./lien-courant
stat -c '%N | inode=%i | type=%F' -- ./lien-courant
stat -L -c '%n | inode=%i | type=%F | taille=%s' -- ./lien-courant

Ces commandes supposent un lien symbolique existant. GNU stat examine normalement le lien lui-même ; -L, ou --dereference, examine sa cible. Un lien cassé peut encore posséder des métadonnées propres alors que sa cible ne peut pas être interrogée.

Pour un lien, la taille propre correspond généralement à la longueur du chemin stocké, pas à la taille du document pointé. Choisissez explicitement la politique voulue dans un script : lire les métadonnées du lien puis traiter sa cible comme si c’était le même objet peut produire des décisions erronées.

Interroger le système de fichiers et son cache

Utiliser les directives propres au mode -f

stat -f -- ./demo-stat
stat -f -c 'type=%T total=%b libre=%f disponible=%a unite=%S' -- ./demo-stat

-f examine le système de fichiers qui contient le chemin et implique le suivi des liens. Les lettres du format changent alors de sens :

Directive avec -f Information
%T Type de système de fichiers sous une forme lisible.
%b Nombre total de blocs de données du système de fichiers.
%f Blocs libres.
%a Blocs disponibles pour un utilisateur non privilégié.
%S Taille fondamentale d’un bloc, en octets, pour ces nombres de blocs.
%c et %d Nombres total et libre de nœuds de fichiers, selon ce que le système fournit.

Ainsi, %a n’est plus le mode en octal du fichier et %b n’est plus son allocation propre. Utilisez %S pour interpréter les nombres de blocs de ce mode, et distinguez l’espace libre de l’espace disponible aux utilisateurs ordinaires. Le type peut rester UNKNOWN si cette version ne reconnaît pas l’identifiant fourni ; ne déduisez pas un autre type à partir de son seul affichage. %m, en mode fichier, affiche le point de montage ; il ne remplace pas à lui seul une analyse complète des montages.

Choisir la fraîcheur des attributs lorsque le système le permet

--cached=default laisse la décision au système de fichiers, --cached=always demande les attributs déjà en cache s’ils sont disponibles et --cached=never demande une synchronisation avec les attributs récents. Vérifiez la disponibilité et le comportement sur votre installation.

Ce compromis concerne notamment NFS (Network File System), un système de fichiers réseau. Une lecture plus fraîche peut coûter un accès distant et le mode never peut aussi provoquer un montage automatique. Ce réglage n’immobilise pas le fichier et ne remplace pas une stratégie de cohérence pour des modifications concurrentes.

Le manuel GNU de stat distingue les directives des deux modes et décrit les options de cache.

Utiliser des métadonnées dans un script complet

Comparer une taille au seuil de 100 MiB

Enregistrez ce script dans un nouveau fichier taille-limite.sh. Un mébioctet, ou MiB, vaut 1 048 576 octets ; le seuil est donc de 104 857 600 octets :

#!/usr/bin/env bash
if [ "$#" -ne 1 ] || [ -z "$1" ]; then
  printf '%s\n' 'Usage : bash taille-limite.sh fichier' >&2
  exit 64
fi
chemin=$1
case $chemin in
  /*) ;;
  *) chemin=./$chemin ;;
esac
if [ ! -f "$chemin" ]; then
  printf '%s\n' 'Un fichier ordinaire est attendu.' >&2
  exit 66
fi

if taille=$(stat -L -c '%s' -- "$chemin"); then
  if [ "$taille" -gt 104857600 ]; then
    printf '%s\n' 'Le fichier depasse 100 MiB.'
  else
    printf '%s\n' 'Le fichier ne depasse pas 100 MiB.'
  fi
else
  statut=$?
  printf '%s\n' 'Impossible de lire la taille.' >&2
  exit "$statut"
fi
bash taille-limite.sh ./demo-stat/rapport.txt

Le fichier de quatre octets ne dépasse pas le seuil. Un fichier dont la taille est exactement 100 MiB ne le dépasse pas non plus ; l’opérateur -gt exprime une comparaison strictement supérieure. Ce classement utilise la taille logique, pas le nombre d’octets alloués sur le stockage.

Le script retourne 64 pour des arguments invalides, 66 si sa cible n’est pas un fichier ordinaire et conserve un échec de stat. Le test de fichier et l’option -L suivent les liens ; le préfixe ./ protège les chemins relatifs commençant par un tiret. Un résultat affiché dans les deux branches n’est pas un échec de commande.

Comparer deux mtime en contrôlant les deux lectures

Enregistrez le script suivant dans comparer-mtime.sh :

#!/usr/bin/env bash
if [ "$#" -ne 2 ] || [ -z "$1" ] || [ -z "$2" ]; then
  printf '%s\n' 'Usage : bash comparer-mtime.sh fichier-gauche fichier-droit' >&2
  exit 64
fi

gauche=$(stat -L -c '%Y' -- "$1") || exit 1
droite=$(stat -L -c '%Y' -- "$2") || exit 1

if [ "$gauche" -gt "$droite" ]; then
  printf '%s\n' 'Le fichier gauche a un mtime plus recent.'
elif [ "$gauche" -lt "$droite" ]; then
  printf '%s\n' 'Le fichier droit a un mtime plus recent.'
else
  printf '%s\n' 'Les mtime sont egaux a la seconde affichee.'
fi
bash comparer-mtime.sh ./demo-stat/rapport.txt ./demo-stat/autre-nom.txt

Les deux liens physiques de l’exercice doivent avoir le même mtime, car ils désignent le même objet. Les lectures en %Y comparent les secondes affichées ; des différences plus fines peuvent être masquées. Un horodatage peut aussi avoir été restauré ou fixé explicitement : « mtime plus récent » ne prouve pas à lui seul quelle version du contenu est la plus récente.

Le script refuse les arguments insuffisants et s’arrête si l’une des deux lectures échoue. Il ne lance aucune modification selon le résultat. Pour une décision de sauvegarde ou de déploiement, choisissez aussi les critères de contenu ou de version nécessaires.

Préserver les noms dans une sortie destinée à un programme

Un format %n %s peut être ambigu si un nom contient des espaces ou des sauts de ligne. Ce bloc Bash complet sépare le nom et sa taille par l’octet NUL, qui ne peut pas faire partie d’un nom de fichier Linux :

(
  set -o pipefail
  stat --printf='%n\0%s\0' -- ./demo-stat/rapport.txt ./demo-stat/autre-nom.txt |
    while IFS= read -r -d '' nom; do
      if ! IFS= read -r -d '' taille; then
        printf '%s\n' 'Enregistrement incomplet.' >&2
        exit 1
      fi
      printf 'Nom : %q ; octets : %s\n' "$nom" "$taille"
    done
)

Le consommateur lit exactement deux champs par entrée. IFS=, read -r et le séparateur NUL évitent un découpage sur les espaces et les sauts de ligne. L’affichage final utilise une représentation protégée du nom avec %q, tandis que pipefail évite de masquer une erreur du producteur.

Un format choisi pour l’automatisation règle la présentation des champs ; il ne résout pas les changements intervenant entre le contrôle et l’utilisation du fichier. Conservez les diagnostics, vérifiez le statut de stat et traitez explicitement les valeurs indisponibles au lieu de les interpréter comme des métadonnées confirmées.