Partage
  • Partager sur Facebook
  • Partager sur Twitter

[bash] Trouver le fichier le plus récent

    12 juillet 2019 à 12:54:56

    Bonjour à tous,

    Tout d'abord, je sais qu'il y a beaucoup de topics à ce sujet mais je n'ai pas trouvé la réponse à mon interrogation.

    Je veux trouver le fichier txt le plus récemment édité dans une arborescence de dossier.

    Mon arborescence se visualise comme ceci:

    Pour l'exemple, les noms des fichiers comportent un nombre correspondant à leur ancienneté. 50 étant le plus ancien et donc 0 le plus récent. (c'est juste pour mieux voir dans l'exemple).

    -DossierMere
    
        --dossierA
    
            fichier50.txt
    
            fichier20.txt
    
            --dossierAa
    
                fichier1.txt
    
        --dossierB
    
           --dossierBa
    
               fichier25.txt


    Il y a plusieurs méthodes pour trouver les fichiers les plus récents mais j'ai trouvé cette combinaison qui paraissait intéressante:

    ls -gotR | grep .\txt$ |head -1

     A noter que je lance cette commande dans le dossier 'DossierMere'

    On a donc le paramète 't' pour ranger les fichiers selon leur date de modification et 'R' pour la récursivité. Après je prends juste les fichiers ayant une extension '.txt' et je n'affiche que le plus récent avec 'head'.

    Le problème c'est la récursivité.

    Pour moi récursif veut dire qu'il s'enfonce dans l'arborescence jusqu'au bout.

    Néanmoins ici, au lieu de me sortir 'fichier1.txt' présent dans 'dossierA/dossierAa', il me sort 'fichier20.txt' qui se trouve dans 'dossierA'.

    Donc observation, la recursivité ne s'enfonce que dans UN dossier et non pas 2 comme je le voudrai.

    Avez vous déjà rencontré ce problème? Avez vous des idées pour faire fonctionner cette commande?

    Merci d'avance!



    -
    Edité par Romain29r 12 juillet 2019 à 12:55:37

    • Partager sur Facebook
    • Partager sur Twitter
      12 juillet 2019 à 13:27:44

      il ne faut pas parser la sortie de ls, c'est source d'erreurs parce que les noms de fichiers peuvent contenir n'importe quel caractère sauf / et le caractère NULL
      find -type f -ianme '*.txt' -printf '%T@ %p\0' | sort -z -k1,1n | tail -n 1 -z | cut -z -d ' ' -f2

      -
      Edité par dantonq 12 juillet 2019 à 13:28:54

      • Partager sur Facebook
      • Partager sur Twitter

      Validez la réponse utile « Un problème clairement exposé est à moitié résolu. » Pas de MP technique

        12 juillet 2019 à 14:15:58

        Merci pour ta réponse!

        J'ai fait quelques ajustements, le paramètre 'z' n'existe pas dans cut et tail et il s'agit de '-iname' pour le début de commande:

        find -type f -iname '*.txt' -printf '%T@ %p\0' | sort -z -k1,1n | tail -n 1 | cut -d ' ' -f2

        Néanmoins, maintenant il me renvoie le fichier le plus vieux :waw: Il n'y a plus de problème concernant l’arborescence, il arrive bien à toute la parcourir, il ne reste plus qu'à "inverser" ce que l'on veut à savoir le fichier le plus récent.

        Je regarde ça, et si vous avez une idée n'hésitez pas !

        Merci :)

        • Partager sur Facebook
        • Partager sur Twitter
          12 juillet 2019 à 14:22:45

          inverse les résultats : utilise head ! :)

          si cut et head/tail n'ont pas d'option NULL le parcours de la liste des fichiers risque de ne pas être correct...

          • Partager sur Facebook
          • Partager sur Twitter

          Validez la réponse utile « Un problème clairement exposé est à moitié résolu. » Pas de MP technique

            12 juillet 2019 à 14:42:49

            J'ai regardé ce que fait head mais je ne comprends pas l'utilité dans le contexte présent:

             head - Afficher le début d'un fichier.

            De plus, j'obtiens cette liste avec la commande. Elle est bien rangée dans l'ordre croissante (je veux l'inverse).

            En effet, on voit bien que 'ancien.txt" est en premier et 'CestCeluiLaLePlusRecent.txt" en dernier. (on notera la qualité des noms des fichiers :ninja:)

            find -type f -iname '*.txt' -printf '%T@ %p\0' | sort -z -k1,1n 

            et la sortie:

            1562923650.0001420000 ./A/C/ancien.txt1562923656.0000050000 ./A/MoinsAncien.txt1562923670.0001380000 ./A/Proche.txt1562923675.0000130000 ./B/Recent.txt1562923890.0000010000 ./B/UltaRecent.txt1562923929.0000340000 ./A/C/VraimentRecent.txt1562924090.0000290000 ./A/C/CeluiLa.txt1562928338.0000050000 ./A/PlusProche.txt1562928391.0000050000 ./B/Cava.txt1562933888.0000400000 ./A/D/CestCeluiLaQuiEstLePlusRecent.txtr
            



            Concernant la date qui se rajoute, dans un premier temps ce n'est pas grave mais j'ai remarqué que quand je change le -printf

            find -type f -iname '*.txt' -printf '%p\0' | sort -z -k1,1n 

            Elle renvoie juste le chemin MAIS du mauvais fichier ET dans le mauvais ordre.

            C'est un problème mois important que le premier.

            • Partager sur Facebook
            • Partager sur Twitter
              12 juillet 2019 à 14:58:56

              sort tri la date en secondes depuis EPOCH (1 janv 1970, 0:00)
              si tu retires la date, le tri ne se fait plus !

              head fait l'inverse de tail !
              i.e. afficher le début d'un fichier, OU de la sortie standard (la sortie du pipe).

              -
              Edité par dantonq 12 juillet 2019 à 14:59:08

              • Partager sur Facebook
              • Partager sur Twitter

              Validez la réponse utile « Un problème clairement exposé est à moitié résolu. » Pas de MP technique

                12 juillet 2019 à 15:05:21

                Ah oui d'accord je comprends!

                Concernant head/tail, le problème vient en fait du fait que je n'ai qu'une seule ligne de retour, donc quand je fais 'tail- n 1', il va bien m'afficher la dernière ligne mais vu qu'il n'y en a qu'une, et bien ce n'est pas très efficace

                • Partager sur Facebook
                • Partager sur Twitter
                  12 juillet 2019 à 16:11:25

                  find -type f -iname '*.txt' -printf '%T@ %p\0' | sort -z -k1,1rn | awk 'BEGIN{RS="\0"} FNR==1{sub(".* ","");print}'
                  utiliser awk à la place de tail|cut
                  • Partager sur Facebook
                  • Partager sur Twitter

                  Validez la réponse utile « Un problème clairement exposé est à moitié résolu. » Pas de MP technique

                    22 juillet 2019 à 8:16:33

                    Cette dernière ligne de commande fonctionne bien! Merci :)
                    • Partager sur Facebook
                    • Partager sur Twitter
                      2 août 2019 à 11:47:32

                      Bonjour!

                      Je ré ouvre le topic car je veux trouver maintenant le 2ème fichier le plus récent.

                      J'ai essayé de changer les paramètres nottament ceux de awk mais ce n'est pas très efficace:

                      Renvoie TOUJOURS le plus récent mais quand je change le paramatre de 'FNR', si je le mets à 2, parfois il va me sortir le 2 ème fichier le plus récent, mais parfois il renvoie juste ".txt". Là, il faut donc mettre comme paramètre 3 et il me renvoie bien le 2ème fichier le plus récent.
                      Auriez vous des pistes de réflexion?
                      Merci d'avance!

                      -
                      Edité par Romain29r 2 août 2019 à 11:48:24

                      • Partager sur Facebook
                      • Partager sur Twitter
                        2 août 2019 à 13:32:58

                        Bonjour,

                        Ton problème vient probablement du nom du fichier: https://www.gnu.org/software/gawk/manual/gawk.html#Leftmost-Longest

                        En précisant un peu la regexp du sub tu peux empêcher cela:

                        sub(/[0-9]+\.[0-9]+ /, "")

                        -
                        Edité par KoaTao 2 août 2019 à 13:33:11

                        • Partager sur Facebook
                        • Partager sur Twitter
                          2 août 2019 à 13:56:24

                          Merci de ta réponse !

                          Néanmoins il ne change pas la valeur de retour, toujours ".txt". Il faudrait réussir à dire que l'on veut absolument quelque chose avant le ".txt"

                          Je fouille, merci d'avance pour vos contributions futures !

                          • Partager sur Facebook
                          • Partager sur Twitter
                            2 août 2019 à 14:27:52

                            C'est quoi le nom du fichier exactement? Je ne vois aucune raison de ne pas avoir tout le nom du fichier.

                            Tu as «.txt» en sortie ou «./.txt» ?

                            Si tu enlèves le sub du programme awk, quelle est la sortie affichée?

                            -
                            Edité par KoaTao 2 août 2019 à 14:31:12

                            • Partager sur Facebook
                            • Partager sur Twitter
                              2 août 2019 à 15:03:25

                              KoaTao a écrit:

                              C'est quoi le nom du fichier exactement? Je ne vois aucune raison de ne pas avoir tout le nom du fichier.

                              Tu as «.txt» en sortie ou «./.txt» ?

                              Si tu enlèves le sub du programme awk, quelle est la sortie affichée?

                              -
                              Edité par KoaTao il y a 21 minutes


                              Le nom du fichier c'est

                              "2019/08/02.txt" , les autres fichiers gardent cette même forme.

                              En sortie j'ai " .txt", et je pense que c'est le caractère espace le problème.

                              Ce que je ne comprends pas, c'est que je n'ai pas de fichier " .txt".

                              Si j'enlève le sub, j'obtiens "1564750849.000138000 2019/08/02.txt" pour FNR=1

                              et donc pour FNR=2 j'obtiens une chaine de nombre différente avec cette fois "nombres...000 .txt"

                              Il faudrait faire en sorte que le nom du fichier ne contienne pas de caractere 'espace' je pense.

                              -
                              Edité par Romain29r 2 août 2019 à 15:03:42

                              • Partager sur Facebook
                              • Partager sur Twitter
                                2 août 2019 à 15:23:10

                                Les espaces dans le nom du fichier ne devrait pas poser de problème.

                                Ton script c'est bien la commande ci-dessous?

                                find -type f -iname '*.txt' -printf '%T@ %p\0' | sort -z -k1,1rn | awk 'BEGIN{RS="\0"} FNR==1{sub(/[0-9]+\.[0-9]+ /,"");print}'

                                Note le «p» minuscule dans le printf de find.

                                Soit tu as un fichier qui se nomme « .txt», sinon faut regarder sans le AWK (je vois pas pourquoi AWK formaterai le nom), puis sans le sort pour essayer de comprendre ce qui formaterai le nom du fichier... Franchement je n'ai aucune idée :(

                                Tu as quelle version de Bash? de find?

                                -
                                Edité par KoaTao 2 août 2019 à 15:25:52

                                • Partager sur Facebook
                                • Partager sur Twitter
                                  2 août 2019 à 15:34:48

                                  Concernant le p minuscule, c'est moi qui avait changé au profit du P majuscule car j'obtiens ce que je veux avec P:

                                  avec p : "./2019/08/02.txt"

                                  avec P : "2019/08/02.txt"

                                  Et ça ne change rien, quand je change le parametre, il me renvoie donc "./.txt"

                                  Sans le AWK... C'est un peu l'anarchie, il me sort les séquences de chiffres suivi du nom de fichier pour chaque fichier de mon arborescence.

                                  Concernant mon bash, je suis sous 4.2.37 et ma distribution est une Wheezy.

                                  Ma version de find est la 4.4.2.

                                  Edit

                                  En re vérifiant pour la 12ème fois,  il y avait en effet un fichier caché ".txt".

                                  Mais le problème est que ce fichier apparait par moments. Hier il n'y était probablement pas puisque ma commande fonctionnait bien avec le paramètre à 2.

                                  Je mettrai à jour le topic s'il se recrée.

                                  Merci pour ces réponses en tout cas ! :)

                                  -
                                  Edité par Romain29r 2 août 2019 à 15:35:13

                                  • Partager sur Facebook
                                  • Partager sur Twitter
                                    2 août 2019 à 15:45:43

                                    Aaah voilà, tout s'explique ^^

                                    La commande dans l'état actuel devrait fonctionner comme tu le souhaites maintenant (sauf s'il y a des noms de fichiers bien vicieux auxquel on aurait pas pensé).

                                    Donc si le .txt se crée, c'est probablement du à autre chose

                                    -
                                    Edité par KoaTao 2 août 2019 à 15:46:09

                                    • Partager sur Facebook
                                    • Partager sur Twitter

                                    [bash] Trouver le fichier le plus récent

                                    × Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
                                    × Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
                                    • Editeur
                                    • Markdown