Contenu | Rechercher | Menus

Annonce

Si vous avez des soucis pour rester connecté, déconnectez-vous puis reconnectez-vous depuis ce lien en cochant la case
Me connecter automatiquement lors de mes prochaines visites.

À propos de l'équipe du forum.

#1 Le 04/07/2018, à 14:18

FalCT60

[Résolu] Combiner find et stat

Bonjour,

C'est sans doute évident pour beaucoup, mais ça fait un moment que je bute là-dessus, alors j'appelle à l'aide tout en continuant de chercher de mon côté.
Je sais à présent (cf. ici) afficher la date de dernier accès des fichiers d'un répertoire.
Malheureusement, je me suis rendu compte que la date affichée peut s'avérer quelque différente de celle que j'aurais été en droit d'attendre.
Que j'utilise

find /chemin/ -iname \*.doc -printf %p\;%Ad\/%Am\/%AY\\r

ou

find /chemin/ -iname \*.doc -printf %p\;%Cd\/%Cm\/%CY\\r

la date ne diffère de celle affichée dans l'explorateur et, en outre, peut changer au fil du temps. C'est sans doute logique, mais ne correspond pas à mes attentes.
En parcourant les sujets déjà traités, je suis tombé sur la commande

debugfs

qui m'a tellement donné mal à la tête que je l'ai vite oubliée, et sur

stat

qui semble plus correspondre à ce que je recherche.
Sauf que, j'ai beau essayer, je ne parviens toujours pas à mes fins.
Dernière tentative en date :

find /chemin/ -iname \*.doc -printf | stat --format=%w\\r

qui m'envoie tout aussi allègrement balader (ballader convient aussi).

Merci d'avance

J.-Luc

Dernière modification par FalCT60 (Le 19/07/2018, à 13:24)

Hors ligne

#2 Le 04/07/2018, à 16:56

Watael

Re : [Résolu] Combiner find et stat

il faudrait nous dire quelle date tu veux :
dernier accès
dernier changement
dernière modification
ou date de création (sachant que cette date n'est pas accessible avec tous les systèmes de fichiers, et ceux qui le peuvent doivent être configurés pour, me souvient-il)


Connected \o/
Welcome to sHell. · eval is evil.

En ligne

#3 Le 04/07/2018, à 18:07

FalCT60

Re : [Résolu] Combiner find et stat

Au final, c'est celle de création qui me semble le mieux convenir.
Ayant fait des recherches et lu pas mal d'articles indiquant l'impossibilité de l'obtenir, je m'étais rabattu sur celles de dernière modification ou de dernier accès, mais j'ai été amené à constater qu'elles ne sont pas constantes.
Du coup, c'est bien celle de création, si possible, que je souhaite obtenir, et j'anticipe déjà ta prochaine question qui découle de ta dernière phrase : le système de fichiers utilisé est NTFS, car disque amovible promené entre 2 Linux et un Windows.

Hors ligne

#4 Le 06/07/2018, à 03:35

Watael

Re : [Résolu] Combiner find et stat

tiens! pour ton mal de crâne avec debugfs :

file=/chemin/nomFichier
inode=$(stat -c %i "$file")
partition=$(df "$file" | sed -n '\@^/dev@s/\([^ ]*\).*/\1/p')
debugfs -R 'stat <'$inode'>' "$partition" 2>/dev/null | sed -n '/crtime/s/.*-- //p'

d'après ce que j'ai pu comprendre ntfs-3g donne accès à cette date de création avec ntfsinfo...


Connected \o/
Welcome to sHell. · eval is evil.

En ligne

#5 Le 06/07/2018, à 17:22

FalCT60

Re : [Résolu] Combiner find et stat

Je te remercie pour ta délicate attention ; c'est du beau ! roll
Le fait est qu'aucune des innombrables pages que j'ai parcourues (et qui, pour la plupart, sont la copie les unes des autres) ne m'a apporté la réponse attendue.
J'ai tout de même fini par me rendre compte que

stat --format=%w /chemin/fichier.doc

me retourne

-

et donc, en clair, que l'information n'est pas disponible.
Cela ne m'indique cependant toujours pas pourquoi

find /chemin/ -iname \*.doc | stat --format=%w

m'envoie sur les roses avec un laconique

stat: opérande manquant
Saisissez « stat --help » pour plus d'informations.

qui ne m'en dit pas plus.
L'opérande étant censé être la valeur retournée par la commande find, et le pipe étant censé la rediriger vers la commande stat, je ne vois pas à quel niveau j'ai pu commettre une erreur dans la syntaxe employée.
J'ouvre une autre discussion

Lister les fichiers donnés d'un volume avec leur date de création

et clôturerai celle-ci ultérieurement.

Hors ligne

#6 Le 06/07/2018, à 17:59

Watael

Re : [Résolu] Combiner find et stat

parce que stat ne lit rien via son entrée standard (stdin), mais uniquement les paramètres passés en arguments/opérandes.

find /chemin -iname "*.doc" -exec stat {} \;

Connected \o/
Welcome to sHell. · eval is evil.

En ligne

#7 Le 06/07/2018, à 20:45

FalCT60

Re : [Résolu] Combiner find et stat

Ah ! voilà donc la raison de mes échecs répétés.:(
Pourtant, je n'ai rien trouvé y faisant allusion dans les différents articles parcourus (p. ex. ici ou ainsi que les différentes variantes de ces pages).
Mais, en effet, cela fonctionne bien de la sorte, sauf que la date de création est inconnue, mais cela me semblait évident au vu de ma tentative précédente. Encore un coup d'épée dans l'eau.
Du coup, je vais voir si je ne peux pas utiliser ta réponse de ce matin avec une boucle du type

for ... do ... done

Bonne soirée,

Et encore merci (je viens de réaliser que c'est déjà toi qui m'avais aidé dans mon précédent sujet).

Hors ligne

#8 Le 08/07/2018, à 00:37

FalCT60

Re : [Résolu] Combiner find et stat

Watael a écrit :

tiens! pour ton mal de crâne avec debugfs :

Je reviens un peu là-dessus, ayant eu le temps de digérer après une autre prise de tête dûe à une facétie d'un lutin farceur.

Watael a écrit :
inode=$(stat -c %i "$file")
partition=$(df "$file" | sed -n '\@^/dev@s/\([^ ]*\).*/\1/p')

Arrête-moi si je m'égare, mais normalement, en modifiant ce membre :

Watael a écrit :
debugfs -R 'stat <'$inode'>' "$partition" 2>/dev/null | sed -n '/crtime/s/.*-- //p'

de la sorte :

date=$(debugfs -R 'stat <'$inode'>' "$partition" 2>/dev/null | sed -n '/crtime/s/.*-- //p')

on devrait pouvoir afficher la date par la commande :

echo -e "$date"

Or, j'obtiens une ligne vide.
Je suis désespérément en train de tenter de retrouver une page sur laquelle j'avais trouvé c'est bon, la voilà
Je savais bien que j'avais déjà lu quelque chose se rapportant à ta dernière remarque

Watael a écrit :

d'après ce que j'ai pu comprendre ntfs-3g donne accès à cette date de création avec ntfsinfo...

Ce qui m'a un peu perturbé, et je me suis focalisé dessus au détriment du reste, c'est tout ce pavé autour de debugfs, alors qu'en théorie il devrait suffire d'invoquer ntfsinfo pour avoir la réponse.
Néanmoins, si je tape

ntfsinfo -F "/media/jean-luc/mes photos/fleur.jpg" /dev/sdb1

j'obtiens une bordée d'injures me signifiant que l'accès à sdb1 m'est refusé parce «qu'il est déjà ouvert, et bla-bla-bla...».
En fin de compte, je me retrouve donc avec deux moyens potentiels d'afficher la date de création, que je ne sais pas faire fonctionner.
Je continue de creuser autour de la page consacrée à ntfsinfo...

Hors ligne

#9 Le 08/07/2018, à 00:57

Watael

Re : [Résolu] Combiner find et stat

ah! 'pas fait gaffe : il faut être root pour utiliser debugfs.

je n'ai pas de FS sous NTFS. sad


Connected \o/
Welcome to sHell. · eval is evil.

En ligne

#10 Le 08/07/2018, à 16:23

FalCT60

Re : [Résolu] Combiner find et stat

Ah ! je me demandais, aussi, pourquoi ton exemple ne faisait pas usage du sudo, contrairement aux autres trouvés çà et là...
Ceci étant, sur la page que j'ai indiquée hier ce matin, j'ai trouvé quelque chose qui semble mieux convenir :

getfattr --only-values -n system.ntfs_times /some/file |
  perl -MPOSIX -0777 -ne 'print ctime unpack(Q)/10000000-11644473600'

Je l'ai appliqué au petit script précédemment utilisé dans l'exemple, modifié pour rechercher toutes les images disques que je conserve (mais je pourrai également m'en servir pour les photos).
Cela donne

# recherche récursive de tous les fichiers d'extension iso sur les disques amovibles connectés et sauvegarde du résultat dans le fichier txt
find /media/jean-luc/ -iname \*.iso > donnees.txt
# exploration de tous les fichiers trouvés pour en déterminer la date de création
while read -r; do
file=$REPLY
# extraction de la date de création de chaque fichier ; ajout du commutateur --absolute-names 
date=$(getfattr --only-values --absolute-names -n system.ntfs_times /some/file | perl -MPOSIX -0777 -ne 'print ctime unpack(Q)/10000000-11644473600')
# affichage sur la console du nom complet du fichier ainsi que de sa date de création
echo -e "$file" "$date"
done < donnees.txt

Le problème est que la date est retournée sous la forme exhaustive, alors que seule m'intéressent le jour, le mois et l'année, à défaut du nombre généralement retourné par la fonction date d'excel.
Je ne comprends pas trop la commande, mais je subodore que c'est le membre après le pipe qui est responsable du formatage.
...
Je crois que j'ai mis le doigt là où je n'aurais pas dû... à côté, debugfs et consorts semblent de la rigolade (j'exagère quand même un peu...).
Bon, faut que je parvienne à retrouver un post dans lequel un intervenant donnait la méthode pour afficher la date et l'heure dans l'ordre correct, et non entremêlés comme dans le cas présent.
Avec un peu de chance, je vais parvenir à avoir quelque chose d'exploitable.
Et voilà, je viens de trouver :

# recherche récursive de tous les fichiers d'extension iso sur les disques amovibles connectés et sauvegarde du résultat dans le fichier txt
find /media/jean-luc/ -iname \*.iso > donnees.txt
# exploration de tous les fichiers trouvés pour en déterminer la date de création
while read -r; do
file=$REPLY
# extraction de la date de création de chaque fichier ; ajout du commutateur --absolute-names 
date=$(getfattr --only-values --absolute-names -n system.ntfs_times /some/file | perl -MPOSIX -0777 -ne 'print ctime unpack(Q)/10000000-11644473600' | sed -n "s/.* \([^ ]*\) \([^ ]*\) \([^ ]*\) \([^ ]*\) \(.*\)/\1 \2 \3 \5 \4/p")
# affichage sur la console du nom complet du fichier ainsi que de sa date de création 
echo -e "$file" "$date"
done < donnees.txt

Bon, un petit bug que je ne suis pas parvenu à identifier fait que le nom du jour ne s'affiche pas et que je ne peux pas intervertir le mois et le jour, mais je ne désespère pas de trouver.

Dernière modification par FalCT60 (Le 08/07/2018, à 17:27)

Hors ligne

#11 Le 08/07/2018, à 17:15

Watael

Re : [Résolu] Combiner find et stat

find /chemin/ -type f -iname '*.iso' -print0 | while read -r -d '' f
do
   printf '%s %s\n' "$f" "$(getfattr...)
done

KISS!*

on doit pouvoir remplacer perl (que je ne connais pas sad ) par quelque chose de plus compréhensible,
mais il faut nous montrer la sortie complète de la commande getfattr pour un fichier exemple.

--
* Keep It Simple Stupid!


Connected \o/
Welcome to sHell. · eval is evil.

En ligne

#12 Le 08/07/2018, à 17:30

FalCT60

Re : [Résolu] Combiner find et stat

Flûte ! j'étais en train de rechercher de mon côté tout en (me) répondant. Je n'ai pas vu celui-là.
La sortie de getfattr est illisible. Je ne me rappelle plus s'il y a moyen de joindre un fichier sur le forum.
Bon, ça m'étonnerait que ça fonctionne,mais à tout hasard je colle la sortie dans un bloc

Þ6úgìÔêƝ#1ÔÞ6úgìÔ,•.Ï<Ô

en espérant que ça ne mette pas la pagaille.
Non, ça semble OK. cool

Dernière modification par FalCT60 (Le 08/07/2018, à 18:15)

Hors ligne

#13 Le 08/07/2018, à 23:22

Watael

Re : [Résolu] Combiner find et stat

Þ6úgìÔêƝ#1ÔÞ6úgìÔ,•.Ï<Ô

ah, ouais ! mais c'est quoi ce K a K a?
et avec --encoding=text, la sortie de getfattr est-elle plus lisible ?


Connected \o/
Welcome to sHell. · eval is evil.

En ligne

#14 Le 09/07/2018, à 16:23

FalCT60

Re : [Résolu] Combiner find et stat

J'ai tenté les trois valeurs possibles, le résultat affiché est toujours le même.
Mes recherches pour tenter de comprendre le fonctionnement de print ctime n'ont rien donné. Ou, plutôt, ont toutes mené à la même page sous ses multiples formes, au point que c'en est décourageant.
Idem pour getfattr.
J'ai également tenté de décortiquer la syntaxe employée par l'auteur pour la commande

sed -n "/crtime/ s/.* -- \([^ ]*\) \([^ ]*\) \([^ ]*\) \([^ ]*\) \(.*\)/\1 \2 \3 \5 \4/p"

postée ici.
D'une part, parce que telle quelle elle ne fonctionne pas chez moi. Pour pouvoir l'utiliser, il me faut la transformer ainsi

sed -n "s/.* \([^ ]*\) \([^ ]*\) \([^ ]*\) \([^ ]*\) \(.*\)/\1 \2 \3 \5 \4/p"

Normal, je pense : ce n'est pas la valeur de crtime que je traite, mais le résultat renvoyé par la commande perl précédente.
Ensuite, il m'a fallu supprimer les "--". Malgré la relecture des pages consacrées à sed, je ne sais toujours pas pourquoi, ni à quoi cela sert.
Enfin, si j'affiche la sortie sans rajouter la commande sed, la date affiche bien le jour de la semaine, le mois, le jour du mois, l'heure et l'année.
Par contre, une fois la section sed rajoutée, le jour de la semaine disparaît et il ne m'est pas possible d'intervertir le jour du mois et le mois, c'est-à-dire que

printf '%s %s\n' "$f" "$(getfattr --only-values --absolute-names -n system.ntfs_times /some/file | perl -MPOSIX -0777 -ne 'print ctime unpack(Q)/10000000-11644473600' | sed -n "s/.* \([^ ]*\) \([^ ]*\) \([^ ]*\) \([^ ]*\) \(.*\)/\1 \2 \3 \5 \4/p")"

donne le même résultat que

printf '%s %s\n' "$f" "$(getfattr --only-values --absolute-names -n system.ntfs_times /some/file | perl -MPOSIX -0777 -ne 'print ctime unpack(Q)/10000000-11644473600' | sed -n "s/.* \([^ ]*\) \([^ ]*\) \([^ ]*\) \([^ ]*\) \(.*\)/\1 \3 \2 \5 \4/p")"

à savoir

Jul 5  2018 00:05:15

Et je déteste ne pas comprendre.
... !!! ... ???
Je viens de trouver... un truc bizarre : cette espace qui se balade entre le jour du mois et l'année avec la séquence

\1 \3 \2 \5 \4

se retrouve entre le mois et le jour avec

\1 \2 \3 \5 \4

et, en mettant

\3 \1 \5

j'obtiens

5 Jul 2018

.
Ceci me semble totalement illogique, mais je tâcherai de me le rappeler pour une prochaine fois.

Dernière modification par FalCT60 (Le 09/07/2018, à 16:38)

Hors ligne

#15 Le 09/07/2018, à 16:30

Watael

Re : [Résolu] Combiner find et stat

mais, la sortie de perl est la même que celle de debugfs ? sinon, à quoi ressemble-t-elle ?


Connected \o/
Welcome to sHell. · eval is evil.

En ligne

#16 Le 09/07/2018, à 16:41

FalCT60

Re : [Résolu] Combiner find et stat

Et re-flûte ! ma manie de rester sur le texte en cours d'édition... hmm
J'avoue ne pas trop comprendre ta question, là. Mais vu que j'ai l'esprit tout embrouillé par les tonnes d'informations que j'ai tenté de décortiquer...

Hors ligne

#17 Le 09/07/2018, à 17:05

Watael

Re : [Résolu] Combiner find et stat

pour faire simple : quelle est la sortie de

printf '%s %s\n' "$f" "$(getfattr --only-values --absolute-names -n system.ntfs_times /some/file | perl -MPOSIX -0777 -ne 'print ctime unpack(Q)/10000000-11644473600'

parce que dire qu'une commande ne fonctionne pas sans nous fournir les données à traiter... hmm


Connected \o/
Welcome to sHell. · eval is evil.

En ligne

#18 Le 09/07/2018, à 17:25

FalCT60

Re : [Résolu] Combiner find et stat

Ah ! oui, bien évidemment.
Il me sort la date sous la forme

Fichier.txt Wed  4 15:44:15 2018

Sortie réelle d'un fichier créé mercredi dernier.
Pour être précis, je ne prétends pas que la commande ne fonctionne pas, mais il m'est évident que sortir une commande de son contexte et la balancer comme ça sans comprendre ce que l'on fait exactement, ce qui est justement mon cas, ne peut que conduire à des comportements plus ou moins inattendus.
Si tu n'avais pas été là, je ne pense pas que j'aurais pu avancer beaucoup.

Hors ligne

#19 Le 09/07/2018, à 18:15

Watael

Re : [Résolu] Combiner find et stat

si elle ne fait pas ce que tu veux, elle ne fonctionne pas ! dans ce contexte. wink

mais j'ai oublié de demander quel format de données tu souhaites obtenir. roll

par défaut, je vais replacer l'année près du mois :

$ echo 'Fichier.txt Wed  4 15:44:15 2018' | sed -r 's/([^\s]*)\s([^\s]*)\s([^\s]*)\s([^\s]*)\s([^\s]*)/\1 \2 \3 \5 \4/'                                                                                                              
Fichier.txt Wed  4 2018 15:44:15

/!\ il y a deux espaces avant la date du mois parce qu'elle ne comporte qu'un seul chiffre, mais elle en aura deux à partir d'octobre.

pour ce qui est du \s, cf. man perlre

Dernière modification par Watael (Le 09/07/2018, à 18:15)


Connected \o/
Welcome to sHell. · eval is evil.

En ligne

#20 Le 09/07/2018, à 19:32

FalCT60

Re : [Résolu] Combiner find et stat

Grrr ! l'inconvénient de travailler sur deux machines et de recopier à la main ! il faut toujours que je me relise 20 fois, et malgré cela je continue à ne pas voir les conneries que j'écris !
C'est

Fichier.txt Wed Jul 4 15:44:15 2018

qu'il me sort.
Après cette petite pause, je devrais avoir les idées un peu plus claires.
Je vais tester le sed depuis une variable intermédiaire contenant la date, et voir si ça ne va pas mieux.
Concernant la commande perl, si j'ai bien compris, 10000000 représente 100 ns et 11644473600 la différence entre le présent et le 01/01/1601.
L'os sur lequel je me casse les dents, c'est ce unpack(Q) dont je ne suis pas parvenu à trouver la définition.
Avec une valeur différente de Q, la date retournée est

Mon Jan  1 00:09:21 1601

Je devrais pouvoir trouver quelque chose...
Bon... à force de recherches, par tâtonnements, je tombe enfin sur une page intéressante, noyée parmi des millions d'autres inutiles.

... nouvelle pause ...

Donc, d'après les dernières informations que j'ai pu récolter, le Q permet de définir le format du buffer alimenté par ctime qui précède la commande depack en tant qu'entier 64 bits.
La valeur retournée est ensuite divisée en 10000000èmes de secondes, d'où l'on soustrait le différentiel au 1er janvier 1601 pour obtenir la date actuelle.
Rassuré de constater qu'il y a des esprits plus tordus que le mien... lol

Dernière modification par FalCT60 (Le 09/07/2018, à 22:38)

Hors ligne

#21 Le 10/07/2018, à 13:33

FalCT60

Re : [Résolu] Combiner find et stat

Watael a écrit :

si elle ne fait pas ce que tu veux, elle ne fonctionne pas ! dans ce contexte. wink

mais j'ai oublié de demander quel format de données tu souhaites obtenir. roll

par défaut, je vais replacer l'année près du mois :

$ echo 'Fichier.txt Wed  4 15:44:15 2018' | sed -r 's/([^\s]*)\s([^\s]*)\s([^\s]*)\s([^\s]*)\s([^\s]*)/\1 \2 \3 \5 \4/'Fichier.txt Wed  4 2018 15:44:15

Ah ! nouvelle syntaxe à analyser.

Watael a écrit :

/!\ il y a deux espaces avant la date du mois parce qu'elle ne comporte qu'un seul chiffre, mais elle en aura deux à partir d'octobre.

En attendant, cette espace fout bien le bordel, comme tu peux le constater avec les résultats des trois sorties ci-dessous :
- interversion heure / année : OK

~$ echo 'Fichier.txt Wed Jul  4 15:44:15 2018' | sed -r 's/([^\s]*)\s([^\s]*)\s([^\s]*)\s([^\s]*)\s([^\s]*)/\1 \2 \3 \5 \4/'
Fichier.txt Wed Jul  4 2018 15:44:15

- Interversion mois / jour : c'est l'espace qui est intervertie avec le jour

~$ echo 'Fichier.txt Wed Jul  4 15:44:15 2018' | sed -r 's/([^\s]*)\s([^\s]*)\s([^\s]*)\s([^\s]*)\s([^\s]*)/\1 \3 \2 \5 \4/'
Fichier.txt Wed Jul 4  2018 15:44:15

- suppression du jour de la semaine : le mois a disparu également, ainsi que tout ce qui précède

~$ echo 'Fichier.txt Wed Jul  4 15:44:15 2018' | sed -r 's/([^\s]*)\s([^\s]*)\s([^\s]*)\s([^\s]*)\s([^\s]*)/\3 \2 \5 \4/'
4  2018 15:44:15
Watael a écrit :

pour ce qui est du \s, cf. man perlre

OK.

Hors ligne

#22 Le 10/07/2018, à 15:03

Watael

Re : [Résolu] Combiner find et stat

c'est bizarre : entre crochets le \s semble n'être pas pris en compte, alors que la regex est validée*.

echo 'Fichier.txt Wed Jul  4 15:44:15 2018' | sed -nr 's/([^ ]*)\s([^ ]*)\s([^ ]*)\s+([^ ]*)\s([^ ]*)\s([^ ]*)/\1 \2 \4 \3 \6 \5/p'                                                                                                  
Fichier.txt Wed 4 Jul 2018 15:44:15 

--
*j'ai fait quelques tests avec l'option -n et la commande p pour vérifier la regex.


Connected \o/
Welcome to sHell. · eval is evil.

En ligne

#23 Le 10/07/2018, à 16:32

FalCT60

Re : [Résolu] Combiner find et stat

Là, ça semble fonctionner correctement. Bien que, une fois de plus, je ne parvienne pas à comprendre qui fait quoi.
En particulier, pourquoi le premier membre est composée de

s/([^ ]*)

tandis que les suivants se présentent sous la forme

\s([^ ]*)

voire, même,

\s+([^ ]*)

Je crois tout de même avoir compris que, dans l'absolu,

[^ ]

signifie que l'on ignore les espaces (ou le(s) symbole(s) suivant l'accent circonflexe.
Ben, non : finalement, c'est justement tout le contraire!

'^'
     Matches the null string at beginning of the pattern space, i.e.
     what appears after the circumflex must appear at the beginning of
     the pattern space.

Pour le reste... sad

roll roll roll
Je viens de réaliser que je ne t'ai même pas remercié pour tous les efforts que tu as déployés à m'aider.
J'ai encore énormément de pain sur la planche, mais ça finira bien par rentrer.
Un énorme merci à toi.
Et je passe ce sujet en résolu.

Dernière modification par FalCT60 (Le 19/07/2018, à 13:24)

Hors ligne