web-dev-qa-db-fra.com

Déterminez si un fichier a été modifié

Sous Linux (en utilisant actuellement le système de fichiers ext4), comment peut-on vérifier rapidement si le contenu d'un fichier a été modifié sans Lecture de l'un de ses contenus?

Est-ce que la commande stat commande une approche recommandée? Je fais actuellement

$ stat --format "%Y" hello.txt

et plus tard, je peux vérifier si la même commande donne la même sortie. Si c'est le cas, je conclus que Hello.txt n'a pas changé.

Mon sentiment est que l'on veut jeter plus de paramètres pour être encore plus sûr. Par exemple, ajouterait la taille du fichier, le nom du fichier, etc., fournirait une "empreinte digitale" encore meilleure du fichier?

Sur ce sujet, je me souviens que mon programme de sauvegarde incrémentielle a toujours été ignoré, éventuellement parce que Truecrypt s'est assuré de ne laisser aucun changement de métadonnées. Je suppose qu'il est en effet possible de changer toutes les données renvoyées par stat, il ne peut donc pas être garanti de la prise en charge de toutes les modifications possibles du fichier?

10
DustByte

Si vous souhaitez détecter si un fichier a été modifié via des moyens normaux (en le modifiant dans une application, consultez une nouvelle version à partir d'un système de contrôle de révision, de la reconstruction, etc.), vérifiez si son temps de modification (MTIME) a ​​changé de le dernier chèque. C'est ce que stat -c %Y rapports.

Le temps de modification peut être défini par la commande touch. Si vous souhaitez détecter si le fichier a changé de quelque manière que ce soit (y compris l'utilisation de touch, extraire une archive, etc.), vérifiez si son temps de changement d'inode (ctime) a changé depuis le dernier chèque. C'est ce que stat -c %Z rapports. Le Time ne peut pas être utilisé à l'exception de l'administrateur système (et même alors, uniquement par des moyens indirects: en modifiant directement l'horloge système, ou en accédant directement au disque, contourner le système de fichiers).

La commande stat n'a qu'une résolution d'une seconde. Donc, si le fichier a été modifié deux fois dans la même seconde, vous pouvez manquer une modification. Les systèmes de fichiers plus récents tels que EXT4 fournissent des horodatages de résolution plus élevés dans les nanosecondes, mais certains des anciens outils n'ont pas encore été rattrapés.

De plus, il est possible que d'autres programmes définissent une durée de modification arbitraire. Vous pouvez voir comment cela peut se produire via la commande tactile.

Si vous êtes préoccupé par l'une de ces deux possibilités, ce ne serait pas une mauvaise idée de regarder également la taille du fichier. C'est ce que Rsync fait quand il recherche des fichiers modifiés.

3
Steve Sether

Mon sentiment est que l'on veut jeter plus de paramètres pour être encore plus sûr.

Ce que vous avez est la méthode correcte. La seule raison pour laquelle l'échec de l'échec serait si le système de fichiers ne met pas à jour correctement - auquel cas vous vous retrouverez avec un tas de problèmes plus graves.

Bien sûr, je présume quelqu'un avec les connaissances appropriées et l'accès root à un système où la partition est accessible peut être capable de modifier les informations pour le faire regarder comme si le fichier n'a pas été modifié. Cependant, dans ce cas, ils auraient sûrement s'assurer de faire la même chose avec la taille, etc.

1
goldilocks

Je fais l'empreinte digitale plus détaillée.

J'ai fait une petite fonction Wrapper qui génère une sortie identique pour les macos/BSD et GNU Versions de stat (détecte également la version installée homebrew avec un g préfixe).

init() {
  if command -v gstat > /dev/null; then
    # GNU coreutils with g prefix.
    statCmdArgs=("gstat" "--format=%n %s %b %u %g %i %h %Y %Z %W %o");
  Elif ! stat --version > /dev/null 2> /dev/null; then
    # MacOS/BSD stat
    statCmdArgs=("stat" "-f" "%N %z %b %u %g %i %l %m %c %B %k");
  else
    # Assume GNU version without prefix.
    statCmdArgs=("stat" "--format=%n %s %b %u %g %i %h %Y %Z %W %o");
  fi;
}

getFileStatus() {
  "${statCmdArgs[@]}" "$1";
}

La fonction init est appelée une fois lors de l'initialisation du script et getFileStatus peut être appelé à plusieurs reprises sans la surcharge de détection.

0
devstuff